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