Line data Source code
1 : /*
2 : * wpa_supplicant/hostapd / common helper functions, etc.
3 : * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 :
13 :
14 344399 : static int hex2num(char c)
15 : {
16 344399 : if (c >= '0' && c <= '9')
17 277259 : return c - '0';
18 67140 : if (c >= 'a' && c <= 'f')
19 60928 : return c - 'a' + 10;
20 6212 : if (c >= 'A' && c <= 'F')
21 6054 : return c - 'A' + 10;
22 158 : return -1;
23 : }
24 :
25 :
26 132642 : int hex2byte(const char *hex)
27 : {
28 : int a, b;
29 132642 : a = hex2num(*hex++);
30 132642 : if (a < 0)
31 69 : return -1;
32 132573 : b = hex2num(*hex++);
33 132573 : if (b < 0)
34 70 : return -1;
35 132503 : return (a << 4) | b;
36 : }
37 :
38 :
39 3352 : static const char * hwaddr_parse(const char *txt, u8 *addr)
40 : {
41 : size_t i;
42 :
43 23070 : for (i = 0; i < ETH_ALEN; i++) {
44 : int a;
45 :
46 19804 : a = hex2byte(txt);
47 19804 : if (a < 0)
48 60 : return NULL;
49 19744 : txt += 2;
50 19744 : addr[i] = a;
51 19744 : if (i < ETH_ALEN - 1 && *txt++ != ':')
52 26 : return NULL;
53 : }
54 3266 : return txt;
55 : }
56 :
57 :
58 : /**
59 : * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
60 : * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
61 : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
62 : * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
63 : */
64 3288 : int hwaddr_aton(const char *txt, u8 *addr)
65 : {
66 3288 : return hwaddr_parse(txt, addr) ? 0 : -1;
67 : }
68 :
69 :
70 : /**
71 : * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format)
72 : * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00")
73 : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
74 : * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes)
75 : * @maskable: Flag to indicate whether a mask is allowed
76 : * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
77 : */
78 47 : int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable)
79 : {
80 : const char *r;
81 :
82 : /* parse address part */
83 47 : r = hwaddr_parse(txt, addr);
84 47 : if (!r)
85 4 : return -1;
86 :
87 : /* check for optional mask */
88 43 : if (*r == '\0' || isspace(*r)) {
89 : /* no mask specified, assume default */
90 25 : os_memset(mask, 0xff, ETH_ALEN);
91 18 : } else if (maskable && *r == '/') {
92 : /* mask specified and allowed */
93 17 : r = hwaddr_parse(r + 1, mask);
94 : /* parser error? */
95 32 : if (!r)
96 2 : return -1;
97 : } else {
98 : /* mask specified but not allowed or trailing garbage */
99 1 : return -1;
100 : }
101 :
102 40 : return 0;
103 : }
104 :
105 :
106 : /**
107 : * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format)
108 : * @txt: MAC address as a string (e.g., "001122334455")
109 : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
110 : * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
111 : */
112 26 : int hwaddr_compact_aton(const char *txt, u8 *addr)
113 : {
114 : int i;
115 :
116 164 : for (i = 0; i < 6; i++) {
117 : int a, b;
118 :
119 141 : a = hex2num(*txt++);
120 141 : if (a < 0)
121 1 : return -1;
122 140 : b = hex2num(*txt++);
123 140 : if (b < 0)
124 2 : return -1;
125 138 : *addr++ = (a << 4) | b;
126 : }
127 :
128 23 : return 0;
129 : }
130 :
131 : /**
132 : * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
133 : * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
134 : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
135 : * Returns: Characters used (> 0) on success, -1 on failure
136 : */
137 6588 : int hwaddr_aton2(const char *txt, u8 *addr)
138 : {
139 : int i;
140 6588 : const char *pos = txt;
141 :
142 46026 : for (i = 0; i < 6; i++) {
143 : int a, b;
144 :
145 111762 : while (*pos == ':' || *pos == '.' || *pos == '-')
146 32854 : pos++;
147 :
148 39454 : a = hex2num(*pos++);
149 39454 : if (a < 0)
150 5 : return -1;
151 39449 : b = hex2num(*pos++);
152 39449 : if (b < 0)
153 11 : return -1;
154 39438 : *addr++ = (a << 4) | b;
155 : }
156 :
157 6572 : return pos - txt;
158 : }
159 :
160 :
161 : /**
162 : * hexstr2bin - Convert ASCII hex string into binary data
163 : * @hex: ASCII hex string (e.g., "01ab")
164 : * @buf: Buffer for the binary data
165 : * @len: Length of the text to convert in bytes (of buf); hex will be double
166 : * this size
167 : * Returns: 0 on success, -1 on failure (invalid hex string)
168 : */
169 5994 : int hexstr2bin(const char *hex, u8 *buf, size_t len)
170 : {
171 : size_t i;
172 : int a;
173 5994 : const char *ipos = hex;
174 5994 : u8 *opos = buf;
175 :
176 118699 : for (i = 0; i < len; i++) {
177 112784 : a = hex2byte(ipos);
178 112784 : if (a < 0)
179 79 : return -1;
180 112705 : *opos++ = a;
181 112705 : ipos += 2;
182 : }
183 5915 : return 0;
184 : }
185 :
186 :
187 37 : int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask)
188 : {
189 : size_t i;
190 37 : int print_mask = 0;
191 : int res;
192 :
193 201 : for (i = 0; i < ETH_ALEN; i++) {
194 176 : if (mask[i] != 0xff) {
195 12 : print_mask = 1;
196 12 : break;
197 : }
198 : }
199 :
200 37 : if (print_mask)
201 144 : res = os_snprintf(buf, len, MACSTR "/" MACSTR,
202 144 : MAC2STR(addr), MAC2STR(mask));
203 : else
204 25 : res = os_snprintf(buf, len, MACSTR, MAC2STR(addr));
205 37 : if (os_snprintf_error(len, res))
206 0 : return -1;
207 37 : return res;
208 : }
209 :
210 :
211 : /**
212 : * inc_byte_array - Increment arbitrary length byte array by one
213 : * @counter: Pointer to byte array
214 : * @len: Length of the counter in bytes
215 : *
216 : * This function increments the last byte of the counter by one and continues
217 : * rolling over to more significant bytes if the byte was incremented from
218 : * 0xff to 0x00.
219 : */
220 4597 : void inc_byte_array(u8 *counter, size_t len)
221 : {
222 4597 : int pos = len - 1;
223 9201 : while (pos >= 0) {
224 4604 : counter[pos]++;
225 4604 : if (counter[pos] != 0)
226 4597 : break;
227 7 : pos--;
228 : }
229 4597 : }
230 :
231 :
232 3387 : void wpa_get_ntp_timestamp(u8 *buf)
233 : {
234 : struct os_time now;
235 : u32 sec, usec;
236 : be32 tmp;
237 :
238 : /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
239 3387 : os_get_time(&now);
240 3387 : sec = now.sec + 2208988800U; /* Epoch to 1900 */
241 : /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
242 3387 : usec = now.usec;
243 3387 : usec = 4295 * usec - (usec >> 5) - (usec >> 9);
244 3387 : tmp = host_to_be32(sec);
245 3387 : os_memcpy(buf, (u8 *) &tmp, 4);
246 3387 : tmp = host_to_be32(usec);
247 3387 : os_memcpy(buf + 4, (u8 *) &tmp, 4);
248 3387 : }
249 :
250 : /**
251 : * wpa_scnprintf - Simpler-to-use snprintf function
252 : * @buf: Output buffer
253 : * @size: Buffer size
254 : * @fmt: format
255 : *
256 : * Simpler snprintf version that doesn't require further error checks - the
257 : * return value only indicates how many bytes were actually written, excluding
258 : * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough).
259 : */
260 109 : int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...)
261 : {
262 : va_list ap;
263 : int ret;
264 :
265 109 : if (!size)
266 0 : return 0;
267 :
268 109 : va_start(ap, fmt);
269 109 : ret = vsnprintf(buf, size, fmt, ap);
270 109 : va_end(ap);
271 :
272 109 : if (ret < 0)
273 0 : return 0;
274 109 : if ((size_t) ret >= size)
275 0 : return size - 1;
276 :
277 109 : return ret;
278 : }
279 :
280 91678 : static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
281 : size_t len, int uppercase)
282 : {
283 : size_t i;
284 91678 : char *pos = buf, *end = buf + buf_size;
285 : int ret;
286 91678 : if (buf_size == 0)
287 0 : return 0;
288 2464908 : for (i = 0; i < len; i++) {
289 2373230 : ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
290 2373230 : data[i]);
291 2373230 : if (os_snprintf_error(end - pos, ret)) {
292 0 : end[-1] = '\0';
293 0 : return pos - buf;
294 : }
295 2373230 : pos += ret;
296 : }
297 91678 : end[-1] = '\0';
298 91678 : return pos - buf;
299 : }
300 :
301 : /**
302 : * wpa_snprintf_hex - Print data as a hex string into a buffer
303 : * @buf: Memory area to use as the output buffer
304 : * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
305 : * @data: Data to be printed
306 : * @len: Length of data in bytes
307 : * Returns: Number of bytes written
308 : */
309 91431 : int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
310 : {
311 91431 : return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
312 : }
313 :
314 :
315 : /**
316 : * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
317 : * @buf: Memory area to use as the output buffer
318 : * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
319 : * @data: Data to be printed
320 : * @len: Length of data in bytes
321 : * Returns: Number of bytes written
322 : */
323 247 : int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
324 : size_t len)
325 : {
326 247 : return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
327 : }
328 :
329 :
330 : #ifdef CONFIG_ANSI_C_EXTRA
331 :
332 : #ifdef _WIN32_WCE
333 : void perror(const char *s)
334 : {
335 : wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
336 : s, (int) GetLastError());
337 : }
338 : #endif /* _WIN32_WCE */
339 :
340 :
341 : int optind = 1;
342 : int optopt;
343 : char *optarg;
344 :
345 : int getopt(int argc, char *const argv[], const char *optstring)
346 : {
347 : static int optchr = 1;
348 : char *cp;
349 :
350 : if (optchr == 1) {
351 : if (optind >= argc) {
352 : /* all arguments processed */
353 : return EOF;
354 : }
355 :
356 : if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
357 : /* no option characters */
358 : return EOF;
359 : }
360 : }
361 :
362 : if (os_strcmp(argv[optind], "--") == 0) {
363 : /* no more options */
364 : optind++;
365 : return EOF;
366 : }
367 :
368 : optopt = argv[optind][optchr];
369 : cp = os_strchr(optstring, optopt);
370 : if (cp == NULL || optopt == ':') {
371 : if (argv[optind][++optchr] == '\0') {
372 : optchr = 1;
373 : optind++;
374 : }
375 : return '?';
376 : }
377 :
378 : if (cp[1] == ':') {
379 : /* Argument required */
380 : optchr = 1;
381 : if (argv[optind][optchr + 1]) {
382 : /* No space between option and argument */
383 : optarg = &argv[optind++][optchr + 1];
384 : } else if (++optind >= argc) {
385 : /* option requires an argument */
386 : return '?';
387 : } else {
388 : /* Argument in the next argv */
389 : optarg = argv[optind++];
390 : }
391 : } else {
392 : /* No argument */
393 : if (argv[optind][++optchr] == '\0') {
394 : optchr = 1;
395 : optind++;
396 : }
397 : optarg = NULL;
398 : }
399 : return *cp;
400 : }
401 : #endif /* CONFIG_ANSI_C_EXTRA */
402 :
403 :
404 : #ifdef CONFIG_NATIVE_WINDOWS
405 : /**
406 : * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
407 : * @str: Pointer to string to convert
408 : *
409 : * This function converts a unicode string to ASCII using the same
410 : * buffer for output. If UNICODE is not set, the buffer is not
411 : * modified.
412 : */
413 : void wpa_unicode2ascii_inplace(TCHAR *str)
414 : {
415 : #ifdef UNICODE
416 : char *dst = (char *) str;
417 : while (*str)
418 : *dst++ = (char) *str++;
419 : *dst = '\0';
420 : #endif /* UNICODE */
421 : }
422 :
423 :
424 : TCHAR * wpa_strdup_tchar(const char *str)
425 : {
426 : #ifdef UNICODE
427 : TCHAR *buf;
428 : buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
429 : if (buf == NULL)
430 : return NULL;
431 : wsprintf(buf, L"%S", str);
432 : return buf;
433 : #else /* UNICODE */
434 : return os_strdup(str);
435 : #endif /* UNICODE */
436 : }
437 : #endif /* CONFIG_NATIVE_WINDOWS */
438 :
439 :
440 181042 : void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
441 : {
442 181042 : char *end = txt + maxlen;
443 : size_t i;
444 :
445 3450690 : for (i = 0; i < len; i++) {
446 3269655 : if (txt + 4 >= end)
447 7 : break;
448 :
449 3269648 : switch (data[i]) {
450 : case '\"':
451 1 : *txt++ = '\\';
452 1 : *txt++ = '\"';
453 1 : break;
454 : case '\\':
455 15 : *txt++ = '\\';
456 15 : *txt++ = '\\';
457 15 : break;
458 : case '\033':
459 1 : *txt++ = '\\';
460 1 : *txt++ = 'e';
461 1 : break;
462 : case '\n':
463 25 : *txt++ = '\\';
464 25 : *txt++ = 'n';
465 25 : break;
466 : case '\r':
467 1 : *txt++ = '\\';
468 1 : *txt++ = 'r';
469 1 : break;
470 : case '\t':
471 1 : *txt++ = '\\';
472 1 : *txt++ = 't';
473 1 : break;
474 : default:
475 3269604 : if (data[i] >= 32 && data[i] <= 127) {
476 3160047 : *txt++ = data[i];
477 : } else {
478 109557 : txt += os_snprintf(txt, end - txt, "\\x%02x",
479 109557 : data[i]);
480 : }
481 3269604 : break;
482 : }
483 : }
484 :
485 181042 : *txt = '\0';
486 181042 : }
487 :
488 :
489 19 : size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
490 : {
491 19 : const char *pos = str;
492 19 : size_t len = 0;
493 : int val;
494 :
495 211 : while (*pos) {
496 173 : if (len + 1 >= maxlen)
497 0 : break;
498 173 : switch (*pos) {
499 : case '\\':
500 88 : pos++;
501 88 : switch (*pos) {
502 : case '\\':
503 2 : buf[len++] = '\\';
504 2 : pos++;
505 2 : break;
506 : case '"':
507 2 : buf[len++] = '"';
508 2 : pos++;
509 2 : break;
510 : case 'n':
511 8 : buf[len++] = '\n';
512 8 : pos++;
513 8 : break;
514 : case 'r':
515 2 : buf[len++] = '\r';
516 2 : pos++;
517 2 : break;
518 : case 't':
519 2 : buf[len++] = '\t';
520 2 : pos++;
521 2 : break;
522 : case 'e':
523 2 : buf[len++] = '\033';
524 2 : pos++;
525 2 : break;
526 : case 'x':
527 54 : pos++;
528 54 : val = hex2byte(pos);
529 54 : if (val < 0) {
530 0 : val = hex2num(*pos);
531 0 : if (val < 0)
532 0 : break;
533 0 : buf[len++] = val;
534 0 : pos++;
535 : } else {
536 54 : buf[len++] = val;
537 54 : pos += 2;
538 : }
539 54 : break;
540 : case '0':
541 : case '1':
542 : case '2':
543 : case '3':
544 : case '4':
545 : case '5':
546 : case '6':
547 : case '7':
548 16 : val = *pos++ - '0';
549 16 : if (*pos >= '0' && *pos <= '7')
550 13 : val = val * 8 + (*pos++ - '0');
551 16 : if (*pos >= '0' && *pos <= '7')
552 13 : val = val * 8 + (*pos++ - '0');
553 16 : buf[len++] = val;
554 16 : break;
555 : default:
556 0 : break;
557 : }
558 88 : break;
559 : default:
560 85 : buf[len++] = *pos++;
561 85 : break;
562 : }
563 : }
564 19 : if (maxlen > len)
565 19 : buf[len] = '\0';
566 :
567 19 : return len;
568 : }
569 :
570 :
571 : /**
572 : * wpa_ssid_txt - Convert SSID to a printable string
573 : * @ssid: SSID (32-octet string)
574 : * @ssid_len: Length of ssid in octets
575 : * Returns: Pointer to a printable string
576 : *
577 : * This function can be used to convert SSIDs into printable form. In most
578 : * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
579 : * does not limit the used character set, so anything could be used in an SSID.
580 : *
581 : * This function uses a static buffer, so only one call can be used at the
582 : * time, i.e., this is not re-entrant and the returned buffer must be used
583 : * before calling this again.
584 : */
585 27320 : const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
586 : {
587 : static char ssid_txt[32 * 4 + 1];
588 :
589 27320 : if (ssid == NULL) {
590 219 : ssid_txt[0] = '\0';
591 219 : return ssid_txt;
592 : }
593 :
594 27101 : printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
595 27101 : return ssid_txt;
596 : }
597 :
598 :
599 16820 : void * __hide_aliasing_typecast(void *foo)
600 : {
601 16820 : return foo;
602 : }
603 :
604 :
605 5136 : char * wpa_config_parse_string(const char *value, size_t *len)
606 : {
607 5136 : if (*value == '"') {
608 : const char *pos;
609 : char *str;
610 4945 : value++;
611 4945 : pos = os_strrchr(value, '"');
612 4945 : if (pos == NULL || pos[1] != '\0')
613 2 : return NULL;
614 4943 : *len = pos - value;
615 4943 : str = dup_binstr(value, *len);
616 4943 : if (str == NULL)
617 0 : return NULL;
618 4943 : return str;
619 191 : } else if (*value == 'P' && value[1] == '"') {
620 : const char *pos;
621 : char *tstr, *str;
622 : size_t tlen;
623 8 : value += 2;
624 8 : pos = os_strrchr(value, '"');
625 8 : if (pos == NULL || pos[1] != '\0')
626 3 : return NULL;
627 5 : tlen = pos - value;
628 5 : tstr = dup_binstr(value, tlen);
629 5 : if (tstr == NULL)
630 0 : return NULL;
631 :
632 5 : str = os_malloc(tlen + 1);
633 5 : if (str == NULL) {
634 0 : os_free(tstr);
635 0 : return NULL;
636 : }
637 :
638 5 : *len = printf_decode((u8 *) str, tlen + 1, tstr);
639 5 : os_free(tstr);
640 :
641 5 : return str;
642 : } else {
643 : u8 *str;
644 183 : size_t tlen, hlen = os_strlen(value);
645 183 : if (hlen & 1)
646 3 : return NULL;
647 180 : tlen = hlen / 2;
648 180 : str = os_malloc(tlen + 1);
649 180 : if (str == NULL)
650 0 : return NULL;
651 180 : if (hexstr2bin(value, str, tlen)) {
652 2 : os_free(str);
653 2 : return NULL;
654 : }
655 178 : str[tlen] = '\0';
656 178 : *len = tlen;
657 178 : return (char *) str;
658 : }
659 : }
660 :
661 :
662 20 : int is_hex(const u8 *data, size_t len)
663 : {
664 : size_t i;
665 :
666 109 : for (i = 0; i < len; i++) {
667 94 : if (data[i] < 32 || data[i] >= 127)
668 5 : return 1;
669 : }
670 15 : return 0;
671 : }
672 :
673 :
674 10073 : size_t merge_byte_arrays(u8 *res, size_t res_len,
675 : const u8 *src1, size_t src1_len,
676 : const u8 *src2, size_t src2_len)
677 : {
678 10073 : size_t len = 0;
679 :
680 10073 : os_memset(res, 0, res_len);
681 :
682 10073 : if (src1) {
683 10073 : if (src1_len >= res_len) {
684 0 : os_memcpy(res, src1, res_len);
685 0 : return res_len;
686 : }
687 :
688 10073 : os_memcpy(res, src1, src1_len);
689 10073 : len += src1_len;
690 : }
691 :
692 10073 : if (src2) {
693 9352 : if (len + src2_len >= res_len) {
694 0 : os_memcpy(res + len, src2, res_len - len);
695 0 : return res_len;
696 : }
697 :
698 9352 : os_memcpy(res + len, src2, src2_len);
699 9352 : len += src2_len;
700 : }
701 :
702 10073 : return len;
703 : }
704 :
705 :
706 10079 : char * dup_binstr(const void *src, size_t len)
707 : {
708 : char *res;
709 :
710 10079 : if (src == NULL)
711 0 : return NULL;
712 10079 : res = os_malloc(len + 1);
713 10079 : if (res == NULL)
714 1 : return NULL;
715 10078 : os_memcpy(res, src, len);
716 10078 : res[len] = '\0';
717 :
718 10078 : return res;
719 : }
720 :
721 :
722 3786 : int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value)
723 : {
724 3786 : struct wpa_freq_range *freq = NULL, *n;
725 3786 : unsigned int count = 0;
726 : const char *pos, *pos2, *pos3;
727 :
728 : /*
729 : * Comma separated list of frequency ranges.
730 : * For example: 2412-2432,2462,5000-6000
731 : */
732 3786 : pos = value;
733 8216 : while (pos && pos[0]) {
734 644 : n = os_realloc_array(freq, count + 1,
735 : sizeof(struct wpa_freq_range));
736 644 : if (n == NULL) {
737 0 : os_free(freq);
738 0 : return -1;
739 : }
740 644 : freq = n;
741 644 : freq[count].min = atoi(pos);
742 644 : pos2 = os_strchr(pos, '-');
743 644 : pos3 = os_strchr(pos, ',');
744 644 : if (pos2 && (!pos3 || pos2 < pos3)) {
745 17 : pos2++;
746 17 : freq[count].max = atoi(pos2);
747 : } else
748 627 : freq[count].max = freq[count].min;
749 644 : pos = pos3;
750 644 : if (pos)
751 21 : pos++;
752 644 : count++;
753 : }
754 :
755 3786 : os_free(res->range);
756 3786 : res->range = freq;
757 3786 : res->num = count;
758 :
759 3786 : return 0;
760 : }
761 :
762 :
763 1392944 : int freq_range_list_includes(const struct wpa_freq_range_list *list,
764 : unsigned int freq)
765 : {
766 : unsigned int i;
767 :
768 1392944 : if (list == NULL)
769 0 : return 0;
770 :
771 1424806 : for (i = 0; i < list->num; i++) {
772 34474 : if (freq >= list->range[i].min && freq <= list->range[i].max)
773 2612 : return 1;
774 : }
775 :
776 1390332 : return 0;
777 : }
778 :
779 :
780 2 : char * freq_range_list_str(const struct wpa_freq_range_list *list)
781 : {
782 : char *buf, *pos, *end;
783 : size_t maxlen;
784 : unsigned int i;
785 : int res;
786 :
787 2 : if (list->num == 0)
788 0 : return NULL;
789 :
790 2 : maxlen = list->num * 30;
791 2 : buf = os_malloc(maxlen);
792 2 : if (buf == NULL)
793 0 : return NULL;
794 2 : pos = buf;
795 2 : end = buf + maxlen;
796 :
797 7 : for (i = 0; i < list->num; i++) {
798 5 : struct wpa_freq_range *range = &list->range[i];
799 :
800 5 : if (range->min == range->max)
801 4 : res = os_snprintf(pos, end - pos, "%s%u",
802 : i == 0 ? "" : ",", range->min);
803 : else
804 1 : res = os_snprintf(pos, end - pos, "%s%u-%u",
805 : i == 0 ? "" : ",",
806 : range->min, range->max);
807 5 : if (os_snprintf_error(end - pos, res)) {
808 0 : os_free(buf);
809 0 : return NULL;
810 : }
811 5 : pos += res;
812 : }
813 :
814 2 : return buf;
815 : }
816 :
817 :
818 4602 : int int_array_len(const int *a)
819 : {
820 : int i;
821 4602 : for (i = 0; a && a[i]; i++)
822 : ;
823 4602 : return i;
824 : }
825 :
826 :
827 863 : void int_array_concat(int **res, const int *a)
828 : {
829 : int reslen, alen, i;
830 : int *n;
831 :
832 863 : reslen = int_array_len(*res);
833 863 : alen = int_array_len(a);
834 :
835 863 : n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
836 863 : if (n == NULL) {
837 0 : os_free(*res);
838 0 : *res = NULL;
839 863 : return;
840 : }
841 2589 : for (i = 0; i <= alen; i++)
842 1726 : n[reslen + i] = a[i];
843 863 : *res = n;
844 : }
845 :
846 :
847 47 : static int freq_cmp(const void *a, const void *b)
848 : {
849 47 : int _a = *(int *) a;
850 47 : int _b = *(int *) b;
851 :
852 47 : if (_a == 0)
853 0 : return 1;
854 47 : if (_b == 0)
855 0 : return -1;
856 47 : return _a - _b;
857 : }
858 :
859 :
860 1721 : void int_array_sort_unique(int *a)
861 : {
862 : int alen;
863 : int i, j;
864 :
865 1721 : if (a == NULL)
866 2596 : return;
867 :
868 846 : alen = int_array_len(a);
869 846 : qsort(a, alen, sizeof(int), freq_cmp);
870 :
871 846 : i = 0;
872 846 : j = 1;
873 1718 : while (a[i] && a[j]) {
874 26 : if (a[i] == a[j]) {
875 22 : j++;
876 22 : continue;
877 : }
878 4 : a[++i] = a[j++];
879 : }
880 846 : if (a[i])
881 846 : i++;
882 846 : a[i] = 0;
883 : }
884 :
885 :
886 1414 : void int_array_add_unique(int **res, int a)
887 : {
888 : int reslen;
889 : int *n;
890 :
891 3108 : for (reslen = 0; *res && (*res)[reslen]; reslen++) {
892 2386 : if ((*res)[reslen] == a)
893 692 : return; /* already in the list */
894 : }
895 :
896 722 : n = os_realloc_array(*res, reslen + 2, sizeof(int));
897 722 : if (n == NULL) {
898 0 : os_free(*res);
899 0 : *res = NULL;
900 0 : return;
901 : }
902 :
903 722 : n[reslen] = a;
904 722 : n[reslen + 1] = 0;
905 :
906 722 : *res = n;
907 : }
908 :
909 :
910 22147 : void str_clear_free(char *str)
911 : {
912 22147 : if (str) {
913 1171 : size_t len = os_strlen(str);
914 1171 : os_memset(str, 0, len);
915 1171 : os_free(str);
916 : }
917 22147 : }
918 :
919 :
920 61167 : void bin_clear_free(void *bin, size_t len)
921 : {
922 61167 : if (bin) {
923 33078 : os_memset(bin, 0, len);
924 33078 : os_free(bin);
925 : }
926 61167 : }
927 :
928 :
929 5 : int random_mac_addr(u8 *addr)
930 : {
931 5 : if (os_get_random(addr, ETH_ALEN) < 0)
932 0 : return -1;
933 5 : addr[0] &= 0xfe; /* unicast */
934 5 : addr[0] |= 0x02; /* locally administered */
935 5 : return 0;
936 : }
937 :
938 :
939 4 : int random_mac_addr_keep_oui(u8 *addr)
940 : {
941 4 : if (os_get_random(addr + 3, 3) < 0)
942 0 : return -1;
943 4 : addr[0] &= 0xfe; /* unicast */
944 4 : addr[0] |= 0x02; /* locally administered */
945 4 : return 0;
946 : }
947 :
948 :
949 : /**
950 : * str_token - Get next token from a string
951 : * @buf: String to tokenize. Note that the string might be modified.
952 : * @delim: String of delimiters
953 : * @context: Pointer to save our context. Should be initialized with
954 : * NULL on the first call, and passed for any further call.
955 : * Returns: The next token, NULL if there are no more valid tokens.
956 : */
957 164 : char * str_token(char *str, const char *delim, char **context)
958 : {
959 164 : char *end, *pos = str;
960 :
961 164 : if (*context)
962 132 : pos = *context;
963 :
964 328 : while (*pos && os_strchr(delim, *pos))
965 0 : pos++;
966 164 : if (!*pos)
967 29 : return NULL;
968 :
969 135 : end = pos + 1;
970 1686 : while (*end && !os_strchr(delim, *end))
971 1416 : end++;
972 :
973 135 : if (*end)
974 104 : *end++ = '\0';
975 :
976 135 : *context = end;
977 135 : return pos;
978 : }
979 :
980 :
981 63 : size_t utf8_unescape(const char *inp, size_t in_size,
982 : char *outp, size_t out_size)
983 : {
984 63 : size_t res_size = 0;
985 :
986 63 : if (!inp || !outp)
987 0 : return 0;
988 :
989 63 : if (!in_size)
990 0 : in_size = os_strlen(inp);
991 :
992 : /* Advance past leading single quote */
993 63 : if (*inp == '\'' && in_size) {
994 63 : inp++;
995 63 : in_size--;
996 : }
997 :
998 1064 : while (in_size--) {
999 1000 : if (res_size >= out_size)
1000 0 : return 0;
1001 :
1002 1000 : switch (*inp) {
1003 : case '\'':
1004 : /* Terminate on bare single quote */
1005 62 : *outp = '\0';
1006 62 : return res_size;
1007 :
1008 : case '\\':
1009 0 : if (!in_size--)
1010 0 : return 0;
1011 0 : inp++;
1012 : /* fall through */
1013 :
1014 : default:
1015 938 : *outp++ = *inp++;
1016 938 : res_size++;
1017 : }
1018 : }
1019 :
1020 : /* NUL terminate if space allows */
1021 1 : if (res_size < out_size)
1022 1 : *outp = '\0';
1023 :
1024 1 : return res_size;
1025 : }
1026 :
1027 :
1028 21 : size_t utf8_escape(const char *inp, size_t in_size,
1029 : char *outp, size_t out_size)
1030 : {
1031 21 : size_t res_size = 0;
1032 :
1033 21 : if (!inp || !outp)
1034 0 : return 0;
1035 :
1036 : /* inp may or may not be NUL terminated, but must be if 0 size
1037 : * is specified */
1038 21 : if (!in_size)
1039 0 : in_size = os_strlen(inp);
1040 :
1041 732 : while (in_size--) {
1042 690 : if (res_size++ >= out_size)
1043 0 : return 0;
1044 :
1045 690 : switch (*inp) {
1046 : case '\\':
1047 : case '\'':
1048 0 : if (res_size++ >= out_size)
1049 0 : return 0;
1050 0 : *outp++ = '\\';
1051 : /* fall through */
1052 :
1053 : default:
1054 690 : *outp++ = *inp++;
1055 690 : break;
1056 : }
1057 : }
1058 :
1059 : /* NUL terminate if space allows */
1060 21 : if (res_size < out_size)
1061 21 : *outp = '\0';
1062 :
1063 21 : return res_size;
1064 : }
|