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 801048 : static int hex2num(char c)
16 : {
17 801048 : if (c >= '0' && c <= '9')
18 633849 : return c - '0';
19 167199 : if (c >= 'a' && c <= 'f')
20 158452 : return c - 'a' + 10;
21 8747 : if (c >= 'A' && c <= 'F')
22 8319 : return c - 'A' + 10;
23 428 : return -1;
24 : }
25 :
26 :
27 338582 : int hex2byte(const char *hex)
28 : {
29 : int a, b;
30 338582 : a = hex2num(*hex++);
31 338582 : if (a < 0)
32 78 : return -1;
33 338504 : b = hex2num(*hex++);
34 338504 : if (b < 0)
35 328 : return -1;
36 338176 : return (a << 4) | b;
37 : }
38 :
39 :
40 7390 : static const char * hwaddr_parse(const char *txt, u8 *addr)
41 : {
42 : size_t i;
43 :
44 49838 : for (i = 0; i < ETH_ALEN; i++) {
45 : int a;
46 :
47 42786 : a = hex2byte(txt);
48 42786 : if (a < 0)
49 308 : return NULL;
50 42478 : txt += 2;
51 42478 : addr[i] = a;
52 42478 : if (i < ETH_ALEN - 1 && *txt++ != ':')
53 30 : return NULL;
54 : }
55 7052 : 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 7326 : int hwaddr_aton(const char *txt, u8 *addr)
66 : {
67 7326 : 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((unsigned char) *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 10317 : int hwaddr_aton2(const char *txt, u8 *addr)
139 : {
140 : int i;
141 10317 : const char *pos = txt;
142 :
143 72117 : for (i = 0; i < 6; i++) {
144 : int a, b;
145 :
146 175125 : while (*pos == ':' || *pos == '.' || *pos == '-')
147 51489 : pos++;
148 :
149 61818 : a = hex2num(*pos++);
150 61818 : if (a < 0)
151 5 : return -1;
152 61813 : b = hex2num(*pos++);
153 61813 : if (b < 0)
154 13 : return -1;
155 61800 : *addr++ = (a << 4) | b;
156 : }
157 :
158 10299 : 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 13209 : int hexstr2bin(const char *hex, u8 *buf, size_t len)
171 : {
172 : size_t i;
173 : int a;
174 13209 : const char *ipos = hex;
175 13209 : u8 *opos = buf;
176 :
177 308852 : for (i = 0; i < len; i++) {
178 295739 : a = hex2byte(ipos);
179 295739 : if (a < 0)
180 96 : return -1;
181 295643 : *opos++ = a;
182 295643 : ipos += 2;
183 : }
184 13113 : 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 7910 : void inc_byte_array(u8 *counter, size_t len)
222 : {
223 7910 : int pos = len - 1;
224 15830 : while (pos >= 0) {
225 7920 : counter[pos]++;
226 7920 : if (counter[pos] != 0)
227 7910 : break;
228 10 : pos--;
229 : }
230 7910 : }
231 :
232 :
233 6023 : 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 6023 : os_get_time(&now);
241 6023 : sec = now.sec + 2208988800U; /* Epoch to 1900 */
242 : /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
243 6023 : usec = now.usec;
244 6023 : usec = 4295 * usec - (usec >> 5) - (usec >> 9);
245 6023 : tmp = host_to_be32(sec);
246 6023 : os_memcpy(buf, (u8 *) &tmp, 4);
247 6023 : tmp = host_to_be32(usec);
248 6023 : os_memcpy(buf + 4, (u8 *) &tmp, 4);
249 6023 : }
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 532 : 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 532 : char *pos = buf, *end = buf + buf_size;
287 : int ret;
288 :
289 532 : if (buf_size == 0)
290 1 : return 0;
291 :
292 9012 : for (i = 0; i < len; i++) {
293 16964 : ret = os_snprintf(pos, end - pos, "%02x%c",
294 8482 : data[i], sep);
295 8482 : if (os_snprintf_error(end - pos, ret)) {
296 1 : end[-1] = '\0';
297 1 : return pos - buf;
298 : }
299 8481 : pos += ret;
300 : }
301 530 : pos[-1] = '\0';
302 530 : return pos - buf;
303 : }
304 :
305 :
306 226046 : 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 226046 : char *pos = buf, *end = buf + buf_size;
311 : int ret;
312 226046 : if (buf_size == 0)
313 1 : return 0;
314 5405719 : for (i = 0; i < len; i++) {
315 5179675 : ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
316 5179675 : data[i]);
317 5179675 : if (os_snprintf_error(end - pos, ret)) {
318 1 : end[-1] = '\0';
319 1 : return pos - buf;
320 : }
321 5179674 : pos += ret;
322 : }
323 226044 : end[-1] = '\0';
324 226044 : 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 225671 : int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
336 : {
337 225671 : 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 375 : int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
350 : size_t len)
351 : {
352 375 : 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 425775 : void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
467 : {
468 425775 : char *end = txt + maxlen;
469 : size_t i;
470 :
471 8295422 : for (i = 0; i < len; i++) {
472 7869654 : if (txt + 4 >= end)
473 7 : break;
474 :
475 7869647 : switch (data[i]) {
476 : case '\"':
477 1 : *txt++ = '\\';
478 1 : *txt++ = '\"';
479 1 : break;
480 : case '\\':
481 30 : *txt++ = '\\';
482 30 : *txt++ = '\\';
483 30 : 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 7869588 : if (data[i] >= 32 && data[i] <= 126) {
502 7598323 : *txt++ = data[i];
503 : } else {
504 271265 : txt += os_snprintf(txt, end - txt, "\\x%02x",
505 271265 : data[i]);
506 : }
507 7869588 : break;
508 : }
509 : }
510 :
511 425775 : *txt = '\0';
512 425775 : }
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 46190 : 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 46190 : if (ssid == NULL) {
616 219 : ssid_txt[0] = '\0';
617 219 : return ssid_txt;
618 : }
619 :
620 45971 : printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
621 45971 : return ssid_txt;
622 : }
623 :
624 :
625 37789 : void * __hide_aliasing_typecast(void *foo)
626 : {
627 37789 : return foo;
628 : }
629 :
630 :
631 12313 : char * wpa_config_parse_string(const char *value, size_t *len)
632 : {
633 12313 : if (*value == '"') {
634 : const char *pos;
635 : char *str;
636 11908 : value++;
637 11908 : pos = os_strrchr(value, '"');
638 11908 : if (pos == NULL || pos[1] != '\0')
639 2 : return NULL;
640 11906 : *len = pos - value;
641 11906 : str = dup_binstr(value, *len);
642 11906 : if (str == NULL)
643 11 : return NULL;
644 11895 : return str;
645 405 : } 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 395 : size_t tlen, hlen = os_strlen(value);
671 395 : if (hlen & 1)
672 4 : return NULL;
673 391 : tlen = hlen / 2;
674 391 : str = os_malloc(tlen + 1);
675 391 : if (str == NULL)
676 2 : return NULL;
677 389 : if (hexstr2bin(value, str, tlen)) {
678 2 : os_free(str);
679 2 : return NULL;
680 : }
681 387 : str[tlen] = '\0';
682 387 : *len = tlen;
683 387 : return (char *) str;
684 : }
685 : }
686 :
687 :
688 74 : int is_hex(const u8 *data, size_t len)
689 : {
690 : size_t i;
691 :
692 388 : for (i = 0; i < len; i++) {
693 320 : if (data[i] < 32 || data[i] >= 127)
694 6 : return 1;
695 : }
696 68 : return 0;
697 : }
698 :
699 :
700 917 : int has_ctrl_char(const u8 *data, size_t len)
701 : {
702 : size_t i;
703 :
704 23807 : for (i = 0; i < len; i++) {
705 22892 : if (data[i] < 32 || data[i] == 127)
706 2 : return 1;
707 : }
708 915 : return 0;
709 : }
710 :
711 :
712 1106 : int has_newline(const char *str)
713 : {
714 19221 : while (*str) {
715 17038 : if (*str == '\n' || *str == '\r')
716 29 : return 1;
717 17009 : str++;
718 : }
719 1077 : return 0;
720 : }
721 :
722 :
723 16643 : size_t merge_byte_arrays(u8 *res, size_t res_len,
724 : const u8 *src1, size_t src1_len,
725 : const u8 *src2, size_t src2_len)
726 : {
727 16643 : size_t len = 0;
728 :
729 16643 : os_memset(res, 0, res_len);
730 :
731 16643 : if (src1) {
732 16642 : if (src1_len >= res_len) {
733 1 : os_memcpy(res, src1, res_len);
734 1 : return res_len;
735 : }
736 :
737 16641 : os_memcpy(res, src1, src1_len);
738 16641 : len += src1_len;
739 : }
740 :
741 16642 : if (src2) {
742 15405 : if (len + src2_len >= res_len) {
743 1 : os_memcpy(res + len, src2, res_len - len);
744 1 : return res_len;
745 : }
746 :
747 15404 : os_memcpy(res + len, src2, src2_len);
748 15404 : len += src2_len;
749 : }
750 :
751 16641 : return len;
752 : }
753 :
754 :
755 21380 : char * dup_binstr(const void *src, size_t len)
756 : {
757 : char *res;
758 :
759 21380 : if (src == NULL)
760 1 : return NULL;
761 21379 : res = os_malloc(len + 1);
762 21379 : if (res == NULL)
763 21 : return NULL;
764 21358 : os_memcpy(res, src, len);
765 21358 : res[len] = '\0';
766 :
767 21358 : return res;
768 : }
769 :
770 :
771 2299 : int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value)
772 : {
773 2299 : struct wpa_freq_range *freq = NULL, *n;
774 2299 : unsigned int count = 0;
775 : const char *pos, *pos2, *pos3;
776 :
777 : /*
778 : * Comma separated list of frequency ranges.
779 : * For example: 2412-2432,2462,5000-6000
780 : */
781 2299 : pos = value;
782 6889 : while (pos && pos[0]) {
783 2295 : n = os_realloc_array(freq, count + 1,
784 : sizeof(struct wpa_freq_range));
785 2295 : if (n == NULL) {
786 4 : os_free(freq);
787 4 : return -1;
788 : }
789 2291 : freq = n;
790 2291 : freq[count].min = atoi(pos);
791 2291 : pos2 = os_strchr(pos, '-');
792 2291 : pos3 = os_strchr(pos, ',');
793 2291 : if (pos2 && (!pos3 || pos2 < pos3)) {
794 29 : pos2++;
795 29 : freq[count].max = atoi(pos2);
796 : } else
797 2262 : freq[count].max = freq[count].min;
798 2291 : pos = pos3;
799 2291 : if (pos)
800 29 : pos++;
801 2291 : count++;
802 : }
803 :
804 2295 : os_free(res->range);
805 2295 : res->range = freq;
806 2295 : res->num = count;
807 :
808 2295 : return 0;
809 : }
810 :
811 :
812 14160825 : int freq_range_list_includes(const struct wpa_freq_range_list *list,
813 : unsigned int freq)
814 : {
815 : unsigned int i;
816 :
817 14160825 : if (list == NULL)
818 1 : return 0;
819 :
820 14294458 : for (i = 0; i < list->num; i++) {
821 144908 : if (freq >= list->range[i].min && freq <= list->range[i].max)
822 11274 : return 1;
823 : }
824 :
825 14149550 : return 0;
826 : }
827 :
828 :
829 4 : char * freq_range_list_str(const struct wpa_freq_range_list *list)
830 : {
831 : char *buf, *pos, *end;
832 : size_t maxlen;
833 : unsigned int i;
834 : int res;
835 :
836 4 : if (list->num == 0)
837 1 : return NULL;
838 :
839 3 : maxlen = list->num * 30;
840 3 : buf = os_malloc(maxlen);
841 3 : if (buf == NULL)
842 0 : return NULL;
843 3 : pos = buf;
844 3 : end = buf + maxlen;
845 :
846 9 : for (i = 0; i < list->num; i++) {
847 6 : struct wpa_freq_range *range = &list->range[i];
848 :
849 6 : if (range->min == range->max)
850 4 : res = os_snprintf(pos, end - pos, "%s%u",
851 : i == 0 ? "" : ",", range->min);
852 : else
853 2 : res = os_snprintf(pos, end - pos, "%s%u-%u",
854 : i == 0 ? "" : ",",
855 : range->min, range->max);
856 6 : if (os_snprintf_error(end - pos, res)) {
857 0 : os_free(buf);
858 0 : return NULL;
859 : }
860 6 : pos += res;
861 : }
862 :
863 3 : return buf;
864 : }
865 :
866 :
867 9170 : int int_array_len(const int *a)
868 : {
869 : int i;
870 9170 : for (i = 0; a && a[i]; i++)
871 : ;
872 9170 : return i;
873 : }
874 :
875 :
876 1472 : void int_array_concat(int **res, const int *a)
877 : {
878 : int reslen, alen, i;
879 : int *n;
880 :
881 1472 : reslen = int_array_len(*res);
882 1472 : alen = int_array_len(a);
883 :
884 1472 : n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
885 1472 : if (n == NULL) {
886 0 : os_free(*res);
887 0 : *res = NULL;
888 1472 : return;
889 : }
890 4448 : for (i = 0; i <= alen; i++)
891 2976 : n[reslen + i] = a[i];
892 1472 : *res = n;
893 : }
894 :
895 :
896 106 : static int freq_cmp(const void *a, const void *b)
897 : {
898 106 : int _a = *(int *) a;
899 106 : int _b = *(int *) b;
900 :
901 106 : if (_a == 0)
902 0 : return 1;
903 106 : if (_b == 0)
904 0 : return -1;
905 106 : return _a - _b;
906 : }
907 :
908 :
909 4158 : void int_array_sort_unique(int *a)
910 : {
911 : int alen;
912 : int i, j;
913 :
914 4158 : if (a == NULL)
915 6861 : return;
916 :
917 1455 : alen = int_array_len(a);
918 1455 : qsort(a, alen, sizeof(int), freq_cmp);
919 :
920 1455 : i = 0;
921 1455 : j = 1;
922 2971 : while (a[i] && a[j]) {
923 61 : if (a[i] == a[j]) {
924 25 : j++;
925 25 : continue;
926 : }
927 36 : a[++i] = a[j++];
928 : }
929 1455 : if (a[i])
930 1455 : i++;
931 1455 : a[i] = 0;
932 : }
933 :
934 :
935 4585 : void int_array_add_unique(int **res, int a)
936 : {
937 : int reslen;
938 : int *n;
939 :
940 6762 : for (reslen = 0; *res && (*res)[reslen]; reslen++) {
941 4377 : if ((*res)[reslen] == a)
942 2200 : return; /* already in the list */
943 : }
944 :
945 2385 : n = os_realloc_array(*res, reslen + 2, sizeof(int));
946 2385 : if (n == NULL) {
947 0 : os_free(*res);
948 0 : *res = NULL;
949 0 : return;
950 : }
951 :
952 2385 : n[reslen] = a;
953 2385 : n[reslen + 1] = 0;
954 :
955 2385 : *res = n;
956 : }
957 :
958 :
959 41023 : void str_clear_free(char *str)
960 : {
961 41023 : if (str) {
962 2100 : size_t len = os_strlen(str);
963 2100 : os_memset(str, 0, len);
964 2100 : os_free(str);
965 : }
966 41023 : }
967 :
968 :
969 2037078 : void bin_clear_free(void *bin, size_t len)
970 : {
971 2037078 : if (bin) {
972 1978558 : os_memset(bin, 0, len);
973 1978558 : os_free(bin);
974 : }
975 2037078 : }
976 :
977 :
978 6 : int random_mac_addr(u8 *addr)
979 : {
980 6 : if (os_get_random(addr, ETH_ALEN) < 0)
981 0 : return -1;
982 6 : addr[0] &= 0xfe; /* unicast */
983 6 : addr[0] |= 0x02; /* locally administered */
984 6 : return 0;
985 : }
986 :
987 :
988 4 : int random_mac_addr_keep_oui(u8 *addr)
989 : {
990 4 : if (os_get_random(addr + 3, 3) < 0)
991 0 : return -1;
992 4 : addr[0] &= 0xfe; /* unicast */
993 4 : addr[0] |= 0x02; /* locally administered */
994 4 : return 0;
995 : }
996 :
997 :
998 : /**
999 : * cstr_token - Get next token from const char string
1000 : * @str: a constant string to tokenize
1001 : * @delim: a string of delimiters
1002 : * @last: a pointer to a character following the returned token
1003 : * It has to be set to NULL for the first call and passed for any
1004 : * further call.
1005 : * Returns: a pointer to token position in str or NULL
1006 : *
1007 : * This function is similar to str_token, but it can be used with both
1008 : * char and const char strings. Differences:
1009 : * - The str buffer remains unmodified
1010 : * - The returned token is not a NULL terminated string, but a token
1011 : * position in str buffer. If a return value is not NULL a size
1012 : * of the returned token could be calculated as (last - token).
1013 : */
1014 1579 : const char * cstr_token(const char *str, const char *delim, const char **last)
1015 : {
1016 1579 : const char *end, *token = str;
1017 :
1018 1579 : if (!str || !delim || !last)
1019 0 : return NULL;
1020 :
1021 1579 : if (*last)
1022 929 : token = *last;
1023 :
1024 3210 : while (*token && os_strchr(delim, *token))
1025 52 : token++;
1026 :
1027 1579 : if (!*token)
1028 564 : return NULL;
1029 :
1030 1015 : end = token + 1;
1031 :
1032 12891 : while (*end && !os_strchr(delim, *end))
1033 10861 : end++;
1034 :
1035 1015 : *last = end;
1036 1015 : return token;
1037 : }
1038 :
1039 :
1040 : /**
1041 : * str_token - Get next token from a string
1042 : * @buf: String to tokenize. Note that the string might be modified.
1043 : * @delim: String of delimiters
1044 : * @context: Pointer to save our context. Should be initialized with
1045 : * NULL on the first call, and passed for any further call.
1046 : * Returns: The next token, NULL if there are no more valid tokens.
1047 : */
1048 938 : char * str_token(char *str, const char *delim, char **context)
1049 : {
1050 938 : char *token = (char *) cstr_token(str, delim, (const char **) context);
1051 :
1052 938 : if (token && **context)
1053 395 : *(*context)++ = '\0';
1054 :
1055 938 : return token;
1056 : }
1057 :
1058 :
1059 152 : size_t utf8_unescape(const char *inp, size_t in_size,
1060 : char *outp, size_t out_size)
1061 : {
1062 152 : size_t res_size = 0;
1063 :
1064 152 : if (!inp || !outp)
1065 2 : return 0;
1066 :
1067 150 : if (!in_size)
1068 1 : in_size = os_strlen(inp);
1069 :
1070 : /* Advance past leading single quote */
1071 150 : if (*inp == '\'' && in_size) {
1072 145 : inp++;
1073 145 : in_size--;
1074 : }
1075 :
1076 2227 : while (in_size--) {
1077 2073 : if (res_size >= out_size)
1078 1 : return 0;
1079 :
1080 2072 : switch (*inp) {
1081 : case '\'':
1082 : /* Terminate on bare single quote */
1083 144 : *outp = '\0';
1084 144 : return res_size;
1085 :
1086 : case '\\':
1087 2 : if (!in_size--)
1088 1 : return 0;
1089 1 : inp++;
1090 : /* fall through */
1091 :
1092 : default:
1093 1927 : *outp++ = *inp++;
1094 1927 : res_size++;
1095 : }
1096 : }
1097 :
1098 : /* NUL terminate if space allows */
1099 4 : if (res_size < out_size)
1100 3 : *outp = '\0';
1101 :
1102 4 : return res_size;
1103 : }
1104 :
1105 :
1106 53 : size_t utf8_escape(const char *inp, size_t in_size,
1107 : char *outp, size_t out_size)
1108 : {
1109 53 : size_t res_size = 0;
1110 :
1111 53 : if (!inp || !outp)
1112 2 : return 0;
1113 :
1114 : /* inp may or may not be NUL terminated, but must be if 0 size
1115 : * is specified */
1116 51 : if (!in_size)
1117 1 : in_size = os_strlen(inp);
1118 :
1119 1622 : while (in_size--) {
1120 1524 : if (res_size++ >= out_size)
1121 3 : return 0;
1122 :
1123 1521 : switch (*inp) {
1124 : case '\\':
1125 : case '\'':
1126 2 : if (res_size++ >= out_size)
1127 1 : return 0;
1128 1 : *outp++ = '\\';
1129 : /* fall through */
1130 :
1131 : default:
1132 1520 : *outp++ = *inp++;
1133 1520 : break;
1134 : }
1135 : }
1136 :
1137 : /* NUL terminate if space allows */
1138 47 : if (res_size < out_size)
1139 46 : *outp = '\0';
1140 :
1141 47 : return res_size;
1142 : }
1143 :
1144 :
1145 61364 : int is_ctrl_char(char c)
1146 : {
1147 61364 : return c > 0 && c < 32;
1148 : }
1149 :
1150 :
1151 : /**
1152 : * ssid_parse - Parse a string that contains SSID in hex or text format
1153 : * @buf: Input NULL terminated string that contains the SSID
1154 : * @ssid: Output SSID
1155 : * Returns: 0 on success, -1 otherwise
1156 : *
1157 : * The SSID has to be enclosed in double quotes for the text format or space
1158 : * or NULL terminated string of hex digits for the hex format. buf can include
1159 : * additional arguments after the SSID.
1160 : */
1161 35 : int ssid_parse(const char *buf, struct wpa_ssid_value *ssid)
1162 : {
1163 : char *tmp, *res, *end;
1164 : size_t len;
1165 :
1166 35 : ssid->ssid_len = 0;
1167 :
1168 35 : tmp = os_strdup(buf);
1169 35 : if (!tmp)
1170 0 : return -1;
1171 :
1172 35 : if (*tmp != '"') {
1173 2 : end = os_strchr(tmp, ' ');
1174 2 : if (end)
1175 2 : *end = '\0';
1176 : } else {
1177 33 : end = os_strchr(tmp + 1, '"');
1178 33 : if (!end) {
1179 0 : os_free(tmp);
1180 0 : return -1;
1181 : }
1182 :
1183 33 : end[1] = '\0';
1184 : }
1185 :
1186 35 : res = wpa_config_parse_string(tmp, &len);
1187 35 : if (res && len <= SSID_MAX_LEN) {
1188 34 : ssid->ssid_len = len;
1189 34 : os_memcpy(ssid->ssid, res, len);
1190 : }
1191 :
1192 35 : os_free(tmp);
1193 35 : os_free(res);
1194 :
1195 35 : return ssid->ssid_len ? 0 : -1;
1196 : }
1197 :
1198 :
1199 1739 : int str_starts(const char *str, const char *start)
1200 : {
1201 1739 : return os_strncmp(str, start, os_strlen(start)) == 0;
1202 : }
|