Branch data 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 : 1836 : static int hex2num(char c)
15 : : {
16 [ + - ][ + + ]: 1836 : if (c >= '0' && c <= '9')
17 : 1183 : return c - '0';
18 [ + - ][ + - ]: 653 : if (c >= 'a' && c <= 'f')
19 : 653 : return c - 'a' + 10;
20 [ # # ][ # # ]: 0 : if (c >= 'A' && c <= 'F')
21 : 0 : return c - 'A' + 10;
22 : 1836 : return -1;
23 : : }
24 : :
25 : :
26 : 918 : int hex2byte(const char *hex)
27 : : {
28 : : int a, b;
29 : 918 : a = hex2num(*hex++);
30 [ - + ]: 918 : if (a < 0)
31 : 0 : return -1;
32 : 918 : b = hex2num(*hex++);
33 [ - + ]: 918 : if (b < 0)
34 : 0 : return -1;
35 : 918 : return (a << 4) | b;
36 : : }
37 : :
38 : :
39 : : /**
40 : : * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
41 : : * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
42 : : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
43 : : * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
44 : : */
45 : 0 : int hwaddr_aton(const char *txt, u8 *addr)
46 : : {
47 : : int i;
48 : :
49 [ # # ]: 0 : for (i = 0; i < 6; i++) {
50 : : int a, b;
51 : :
52 : 0 : a = hex2num(*txt++);
53 [ # # ]: 0 : if (a < 0)
54 : 0 : return -1;
55 : 0 : b = hex2num(*txt++);
56 [ # # ]: 0 : if (b < 0)
57 : 0 : return -1;
58 : 0 : *addr++ = (a << 4) | b;
59 [ # # ][ # # ]: 0 : if (i < 5 && *txt++ != ':')
60 : 0 : return -1;
61 : : }
62 : :
63 : 0 : return 0;
64 : : }
65 : :
66 : : /**
67 : : * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format)
68 : : * @txt: MAC address as a string (e.g., "001122334455")
69 : : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
70 : : * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
71 : : */
72 : 0 : int hwaddr_compact_aton(const char *txt, u8 *addr)
73 : : {
74 : : int i;
75 : :
76 [ # # ]: 0 : for (i = 0; i < 6; i++) {
77 : : int a, b;
78 : :
79 : 0 : a = hex2num(*txt++);
80 [ # # ]: 0 : if (a < 0)
81 : 0 : return -1;
82 : 0 : b = hex2num(*txt++);
83 [ # # ]: 0 : if (b < 0)
84 : 0 : return -1;
85 : 0 : *addr++ = (a << 4) | b;
86 : : }
87 : :
88 : 0 : return 0;
89 : : }
90 : :
91 : : /**
92 : : * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
93 : : * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
94 : : * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
95 : : * Returns: Characters used (> 0) on success, -1 on failure
96 : : */
97 : 0 : int hwaddr_aton2(const char *txt, u8 *addr)
98 : : {
99 : : int i;
100 : 0 : const char *pos = txt;
101 : :
102 [ # # ]: 0 : for (i = 0; i < 6; i++) {
103 : : int a, b;
104 : :
105 [ # # ][ # # ]: 0 : while (*pos == ':' || *pos == '.' || *pos == '-')
[ # # ]
106 : 0 : pos++;
107 : :
108 : 0 : a = hex2num(*pos++);
109 [ # # ]: 0 : if (a < 0)
110 : 0 : return -1;
111 : 0 : b = hex2num(*pos++);
112 [ # # ]: 0 : if (b < 0)
113 : 0 : return -1;
114 : 0 : *addr++ = (a << 4) | b;
115 : : }
116 : :
117 : 0 : return pos - txt;
118 : : }
119 : :
120 : :
121 : : /**
122 : : * hexstr2bin - Convert ASCII hex string into binary data
123 : : * @hex: ASCII hex string (e.g., "01ab")
124 : : * @buf: Buffer for the binary data
125 : : * @len: Length of the text to convert in bytes (of buf); hex will be double
126 : : * this size
127 : : * Returns: 0 on success, -1 on failure (invalid hex string)
128 : : */
129 : 77 : int hexstr2bin(const char *hex, u8 *buf, size_t len)
130 : : {
131 : : size_t i;
132 : : int a;
133 : 77 : const char *ipos = hex;
134 : 77 : u8 *opos = buf;
135 : :
136 [ + + ]: 995 : for (i = 0; i < len; i++) {
137 : 918 : a = hex2byte(ipos);
138 [ - + ]: 918 : if (a < 0)
139 : 0 : return -1;
140 : 918 : *opos++ = a;
141 : 918 : ipos += 2;
142 : : }
143 : 77 : return 0;
144 : : }
145 : :
146 : :
147 : : /**
148 : : * inc_byte_array - Increment arbitrary length byte array by one
149 : : * @counter: Pointer to byte array
150 : : * @len: Length of the counter in bytes
151 : : *
152 : : * This function increments the last byte of the counter by one and continues
153 : : * rolling over to more significant bytes if the byte was incremented from
154 : : * 0xff to 0x00.
155 : : */
156 : 0 : void inc_byte_array(u8 *counter, size_t len)
157 : : {
158 : 0 : int pos = len - 1;
159 [ # # ]: 0 : while (pos >= 0) {
160 : 0 : counter[pos]++;
161 [ # # ]: 0 : if (counter[pos] != 0)
162 : 0 : break;
163 : 0 : pos--;
164 : : }
165 : 0 : }
166 : :
167 : :
168 : 0 : void wpa_get_ntp_timestamp(u8 *buf)
169 : : {
170 : : struct os_time now;
171 : : u32 sec, usec;
172 : : be32 tmp;
173 : :
174 : : /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
175 : 0 : os_get_time(&now);
176 : 0 : sec = now.sec + 2208988800U; /* Epoch to 1900 */
177 : : /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
178 : 0 : usec = now.usec;
179 : 0 : usec = 4295 * usec - (usec >> 5) - (usec >> 9);
180 : 0 : tmp = host_to_be32(sec);
181 : 0 : os_memcpy(buf, (u8 *) &tmp, 4);
182 : 0 : tmp = host_to_be32(usec);
183 : 0 : os_memcpy(buf + 4, (u8 *) &tmp, 4);
184 : 0 : }
185 : :
186 : :
187 : 111 : static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
188 : : size_t len, int uppercase)
189 : : {
190 : : size_t i;
191 : 111 : char *pos = buf, *end = buf + buf_size;
192 : : int ret;
193 [ - + ]: 111 : if (buf_size == 0)
194 : 0 : return 0;
195 [ + + ]: 1587 : for (i = 0; i < len; i++) {
196 [ + + ]: 1476 : ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
197 : 1476 : data[i]);
198 [ + - ][ - + ]: 1476 : if (ret < 0 || ret >= end - pos) {
199 : 0 : end[-1] = '\0';
200 : 0 : return pos - buf;
201 : : }
202 : 1476 : pos += ret;
203 : : }
204 : 111 : end[-1] = '\0';
205 : 111 : return pos - buf;
206 : : }
207 : :
208 : : /**
209 : : * wpa_snprintf_hex - Print data as a hex string into a buffer
210 : : * @buf: Memory area to use as the output buffer
211 : : * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
212 : : * @data: Data to be printed
213 : : * @len: Length of data in bytes
214 : : * Returns: Number of bytes written
215 : : */
216 : 84 : int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
217 : : {
218 : 84 : return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
219 : : }
220 : :
221 : :
222 : : /**
223 : : * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
224 : : * @buf: Memory area to use as the output buffer
225 : : * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
226 : : * @data: Data to be printed
227 : : * @len: Length of data in bytes
228 : : * Returns: Number of bytes written
229 : : */
230 : 27 : int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
231 : : size_t len)
232 : : {
233 : 27 : return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
234 : : }
235 : :
236 : :
237 : : #ifdef CONFIG_ANSI_C_EXTRA
238 : :
239 : : #ifdef _WIN32_WCE
240 : : void perror(const char *s)
241 : : {
242 : : wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
243 : : s, (int) GetLastError());
244 : : }
245 : : #endif /* _WIN32_WCE */
246 : :
247 : :
248 : : int optind = 1;
249 : : int optopt;
250 : : char *optarg;
251 : :
252 : : int getopt(int argc, char *const argv[], const char *optstring)
253 : : {
254 : : static int optchr = 1;
255 : : char *cp;
256 : :
257 : : if (optchr == 1) {
258 : : if (optind >= argc) {
259 : : /* all arguments processed */
260 : : return EOF;
261 : : }
262 : :
263 : : if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
264 : : /* no option characters */
265 : : return EOF;
266 : : }
267 : : }
268 : :
269 : : if (os_strcmp(argv[optind], "--") == 0) {
270 : : /* no more options */
271 : : optind++;
272 : : return EOF;
273 : : }
274 : :
275 : : optopt = argv[optind][optchr];
276 : : cp = os_strchr(optstring, optopt);
277 : : if (cp == NULL || optopt == ':') {
278 : : if (argv[optind][++optchr] == '\0') {
279 : : optchr = 1;
280 : : optind++;
281 : : }
282 : : return '?';
283 : : }
284 : :
285 : : if (cp[1] == ':') {
286 : : /* Argument required */
287 : : optchr = 1;
288 : : if (argv[optind][optchr + 1]) {
289 : : /* No space between option and argument */
290 : : optarg = &argv[optind++][optchr + 1];
291 : : } else if (++optind >= argc) {
292 : : /* option requires an argument */
293 : : return '?';
294 : : } else {
295 : : /* Argument in the next argv */
296 : : optarg = argv[optind++];
297 : : }
298 : : } else {
299 : : /* No argument */
300 : : if (argv[optind][++optchr] == '\0') {
301 : : optchr = 1;
302 : : optind++;
303 : : }
304 : : optarg = NULL;
305 : : }
306 : : return *cp;
307 : : }
308 : : #endif /* CONFIG_ANSI_C_EXTRA */
309 : :
310 : :
311 : : #ifdef CONFIG_NATIVE_WINDOWS
312 : : /**
313 : : * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
314 : : * @str: Pointer to string to convert
315 : : *
316 : : * This function converts a unicode string to ASCII using the same
317 : : * buffer for output. If UNICODE is not set, the buffer is not
318 : : * modified.
319 : : */
320 : : void wpa_unicode2ascii_inplace(TCHAR *str)
321 : : {
322 : : #ifdef UNICODE
323 : : char *dst = (char *) str;
324 : : while (*str)
325 : : *dst++ = (char) *str++;
326 : : *dst = '\0';
327 : : #endif /* UNICODE */
328 : : }
329 : :
330 : :
331 : : TCHAR * wpa_strdup_tchar(const char *str)
332 : : {
333 : : #ifdef UNICODE
334 : : TCHAR *buf;
335 : : buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
336 : : if (buf == NULL)
337 : : return NULL;
338 : : wsprintf(buf, L"%S", str);
339 : : return buf;
340 : : #else /* UNICODE */
341 : : return os_strdup(str);
342 : : #endif /* UNICODE */
343 : : }
344 : : #endif /* CONFIG_NATIVE_WINDOWS */
345 : :
346 : :
347 : 0 : void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
348 : : {
349 : 0 : char *end = txt + maxlen;
350 : : size_t i;
351 : :
352 [ # # ]: 0 : for (i = 0; i < len; i++) {
353 [ # # ]: 0 : if (txt + 4 > end)
354 : 0 : break;
355 : :
356 [ # # # # : 0 : switch (data[i]) {
# # # ]
357 : : case '\"':
358 : 0 : *txt++ = '\\';
359 : 0 : *txt++ = '\"';
360 : 0 : break;
361 : : case '\\':
362 : 0 : *txt++ = '\\';
363 : 0 : *txt++ = '\\';
364 : 0 : break;
365 : : case '\e':
366 : 0 : *txt++ = '\\';
367 : 0 : *txt++ = 'e';
368 : 0 : break;
369 : : case '\n':
370 : 0 : *txt++ = '\\';
371 : 0 : *txt++ = 'n';
372 : 0 : break;
373 : : case '\r':
374 : 0 : *txt++ = '\\';
375 : 0 : *txt++ = 'r';
376 : 0 : break;
377 : : case '\t':
378 : 0 : *txt++ = '\\';
379 : 0 : *txt++ = 't';
380 : 0 : break;
381 : : default:
382 [ # # ][ # # ]: 0 : if (data[i] >= 32 && data[i] <= 127) {
383 : 0 : *txt++ = data[i];
384 : : } else {
385 : 0 : txt += os_snprintf(txt, end - txt, "\\x%02x",
386 : 0 : data[i]);
387 : : }
388 : 0 : break;
389 : : }
390 : : }
391 : :
392 : 0 : *txt = '\0';
393 : 0 : }
394 : :
395 : :
396 : 0 : size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
397 : : {
398 : 0 : const char *pos = str;
399 : 0 : size_t len = 0;
400 : : int val;
401 : :
402 [ # # ]: 0 : while (*pos) {
403 [ # # ]: 0 : if (len + 1 >= maxlen)
404 : 0 : break;
405 [ # # ]: 0 : switch (*pos) {
406 : : case '\\':
407 : 0 : pos++;
408 [ # # # # : 0 : switch (*pos) {
# # # #
# ]
409 : : case '\\':
410 : 0 : buf[len++] = '\\';
411 : 0 : pos++;
412 : 0 : break;
413 : : case '"':
414 : 0 : buf[len++] = '"';
415 : 0 : pos++;
416 : 0 : break;
417 : : case 'n':
418 : 0 : buf[len++] = '\n';
419 : 0 : pos++;
420 : 0 : break;
421 : : case 'r':
422 : 0 : buf[len++] = '\r';
423 : 0 : pos++;
424 : 0 : break;
425 : : case 't':
426 : 0 : buf[len++] = '\t';
427 : 0 : pos++;
428 : 0 : break;
429 : : case 'e':
430 : 0 : buf[len++] = '\e';
431 : 0 : pos++;
432 : 0 : break;
433 : : case 'x':
434 : 0 : pos++;
435 : 0 : val = hex2byte(pos);
436 [ # # ]: 0 : if (val < 0) {
437 : 0 : val = hex2num(*pos);
438 [ # # ]: 0 : if (val < 0)
439 : 0 : break;
440 : 0 : buf[len++] = val;
441 : 0 : pos++;
442 : : } else {
443 : 0 : buf[len++] = val;
444 : 0 : pos += 2;
445 : : }
446 : 0 : break;
447 : : case '0':
448 : : case '1':
449 : : case '2':
450 : : case '3':
451 : : case '4':
452 : : case '5':
453 : : case '6':
454 : : case '7':
455 : 0 : val = *pos++ - '0';
456 [ # # ][ # # ]: 0 : if (*pos >= '0' && *pos <= '7')
457 : 0 : val = val * 8 + (*pos++ - '0');
458 [ # # ][ # # ]: 0 : if (*pos >= '0' && *pos <= '7')
459 : 0 : val = val * 8 + (*pos++ - '0');
460 : 0 : buf[len++] = val;
461 : 0 : break;
462 : : default:
463 : 0 : break;
464 : : }
465 : 0 : break;
466 : : default:
467 : 0 : buf[len++] = *pos++;
468 : 0 : break;
469 : : }
470 : : }
471 [ # # ]: 0 : if (maxlen > len)
472 : 0 : buf[len] = '\0';
473 : :
474 : 0 : return len;
475 : : }
476 : :
477 : :
478 : : /**
479 : : * wpa_ssid_txt - Convert SSID to a printable string
480 : : * @ssid: SSID (32-octet string)
481 : : * @ssid_len: Length of ssid in octets
482 : : * Returns: Pointer to a printable string
483 : : *
484 : : * This function can be used to convert SSIDs into printable form. In most
485 : : * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
486 : : * does not limit the used character set, so anything could be used in an SSID.
487 : : *
488 : : * This function uses a static buffer, so only one call can be used at the
489 : : * time, i.e., this is not re-entrant and the returned buffer must be used
490 : : * before calling this again.
491 : : */
492 : 0 : const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
493 : : {
494 : : static char ssid_txt[32 * 4 + 1];
495 : :
496 [ # # ]: 0 : if (ssid == NULL) {
497 : 0 : ssid_txt[0] = '\0';
498 : 0 : return ssid_txt;
499 : : }
500 : :
501 : 0 : printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
502 : 0 : return ssid_txt;
503 : : }
504 : :
505 : :
506 : 0 : void * __hide_aliasing_typecast(void *foo)
507 : : {
508 : 0 : return foo;
509 : : }
510 : :
511 : :
512 : 0 : char * wpa_config_parse_string(const char *value, size_t *len)
513 : : {
514 [ # # ]: 0 : if (*value == '"') {
515 : : const char *pos;
516 : : char *str;
517 : 0 : value++;
518 : 0 : pos = os_strrchr(value, '"');
519 [ # # ][ # # ]: 0 : if (pos == NULL || pos[1] != '\0')
520 : 0 : return NULL;
521 : 0 : *len = pos - value;
522 : 0 : str = dup_binstr(value, *len);
523 [ # # ]: 0 : if (str == NULL)
524 : 0 : return NULL;
525 : 0 : return str;
526 [ # # ][ # # ]: 0 : } else if (*value == 'P' && value[1] == '"') {
527 : : const char *pos;
528 : : char *tstr, *str;
529 : : size_t tlen;
530 : 0 : value += 2;
531 : 0 : pos = os_strrchr(value, '"');
532 [ # # ][ # # ]: 0 : if (pos == NULL || pos[1] != '\0')
533 : 0 : return NULL;
534 : 0 : tlen = pos - value;
535 : 0 : tstr = dup_binstr(value, tlen);
536 [ # # ]: 0 : if (tstr == NULL)
537 : 0 : return NULL;
538 : :
539 : 0 : str = os_malloc(tlen + 1);
540 [ # # ]: 0 : if (str == NULL) {
541 : 0 : os_free(tstr);
542 : 0 : return NULL;
543 : : }
544 : :
545 : 0 : *len = printf_decode((u8 *) str, tlen + 1, tstr);
546 : 0 : os_free(tstr);
547 : :
548 : 0 : return str;
549 : : } else {
550 : : u8 *str;
551 : 0 : size_t tlen, hlen = os_strlen(value);
552 [ # # ]: 0 : if (hlen & 1)
553 : 0 : return NULL;
554 : 0 : tlen = hlen / 2;
555 : 0 : str = os_malloc(tlen + 1);
556 [ # # ]: 0 : if (str == NULL)
557 : 0 : return NULL;
558 [ # # ]: 0 : if (hexstr2bin(value, str, tlen)) {
559 : 0 : os_free(str);
560 : 0 : return NULL;
561 : : }
562 : 0 : str[tlen] = '\0';
563 : 0 : *len = tlen;
564 : 0 : return (char *) str;
565 : : }
566 : : }
567 : :
568 : :
569 : 0 : int is_hex(const u8 *data, size_t len)
570 : : {
571 : : size_t i;
572 : :
573 [ # # ]: 0 : for (i = 0; i < len; i++) {
574 [ # # ][ # # ]: 0 : if (data[i] < 32 || data[i] >= 127)
575 : 0 : return 1;
576 : : }
577 : 0 : return 0;
578 : : }
579 : :
580 : :
581 : 0 : int find_first_bit(u32 value)
582 : : {
583 : 0 : int pos = 0;
584 : :
585 [ # # ]: 0 : while (value) {
586 [ # # ]: 0 : if (value & 0x1)
587 : 0 : return pos;
588 : 0 : value >>= 1;
589 : 0 : pos++;
590 : : }
591 : :
592 : 0 : return -1;
593 : : }
594 : :
595 : :
596 : 0 : size_t merge_byte_arrays(u8 *res, size_t res_len,
597 : : const u8 *src1, size_t src1_len,
598 : : const u8 *src2, size_t src2_len)
599 : : {
600 : 0 : size_t len = 0;
601 : :
602 : 0 : os_memset(res, 0, res_len);
603 : :
604 [ # # ]: 0 : if (src1) {
605 [ # # ]: 0 : if (src1_len >= res_len) {
606 : 0 : os_memcpy(res, src1, res_len);
607 : 0 : return res_len;
608 : : }
609 : :
610 : 0 : os_memcpy(res, src1, src1_len);
611 : 0 : len += src1_len;
612 : : }
613 : :
614 [ # # ]: 0 : if (src2) {
615 [ # # ]: 0 : if (len + src2_len >= res_len) {
616 : 0 : os_memcpy(res + len, src2, res_len - len);
617 : 0 : return res_len;
618 : : }
619 : :
620 : 0 : os_memcpy(res + len, src2, src2_len);
621 : 0 : len += src2_len;
622 : : }
623 : :
624 : 0 : return len;
625 : : }
626 : :
627 : :
628 : 23 : char * dup_binstr(const void *src, size_t len)
629 : : {
630 : : char *res;
631 : :
632 [ - + ]: 23 : if (src == NULL)
633 : 0 : return NULL;
634 : 23 : res = os_malloc(len + 1);
635 [ - + ]: 23 : if (res == NULL)
636 : 0 : return NULL;
637 : 23 : os_memcpy(res, src, len);
638 : 23 : res[len] = '\0';
639 : :
640 : 23 : return res;
641 : : }
642 : :
643 : :
644 : 0 : int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value)
645 : : {
646 : 0 : struct wpa_freq_range *freq = NULL, *n;
647 : 0 : unsigned int count = 0;
648 : : const char *pos, *pos2, *pos3;
649 : :
650 : : /*
651 : : * Comma separated list of frequency ranges.
652 : : * For example: 2412-2432,2462,5000-6000
653 : : */
654 : 0 : pos = value;
655 [ # # ][ # # ]: 0 : while (pos && pos[0]) {
656 : 0 : n = os_realloc_array(freq, count + 1,
657 : : sizeof(struct wpa_freq_range));
658 [ # # ]: 0 : if (n == NULL) {
659 : 0 : os_free(freq);
660 : 0 : return -1;
661 : : }
662 : 0 : freq = n;
663 : 0 : freq[count].min = atoi(pos);
664 : 0 : pos2 = os_strchr(pos, '-');
665 : 0 : pos3 = os_strchr(pos, ',');
666 [ # # ][ # # ]: 0 : if (pos2 && (!pos3 || pos2 < pos3)) {
[ # # ]
667 : 0 : pos2++;
668 : 0 : freq[count].max = atoi(pos2);
669 : : } else
670 : 0 : freq[count].max = freq[count].min;
671 : 0 : pos = pos3;
672 [ # # ]: 0 : if (pos)
673 : 0 : pos++;
674 : 0 : count++;
675 : : }
676 : :
677 : 0 : os_free(res->range);
678 : 0 : res->range = freq;
679 : 0 : res->num = count;
680 : :
681 : 0 : return 0;
682 : : }
683 : :
684 : :
685 : 0 : int freq_range_list_includes(const struct wpa_freq_range_list *list,
686 : : unsigned int freq)
687 : : {
688 : : unsigned int i;
689 : :
690 [ # # ]: 0 : if (list == NULL)
691 : 0 : return 0;
692 : :
693 [ # # ]: 0 : for (i = 0; i < list->num; i++) {
694 [ # # ][ # # ]: 0 : if (freq >= list->range[i].min && freq <= list->range[i].max)
695 : 0 : return 1;
696 : : }
697 : :
698 : 0 : return 0;
699 : : }
700 : :
701 : :
702 : 0 : char * freq_range_list_str(const struct wpa_freq_range_list *list)
703 : : {
704 : : char *buf, *pos, *end;
705 : : size_t maxlen;
706 : : unsigned int i;
707 : : int res;
708 : :
709 [ # # ]: 0 : if (list->num == 0)
710 : 0 : return NULL;
711 : :
712 : 0 : maxlen = list->num * 30;
713 : 0 : buf = os_malloc(maxlen);
714 [ # # ]: 0 : if (buf == NULL)
715 : 0 : return NULL;
716 : 0 : pos = buf;
717 : 0 : end = buf + maxlen;
718 : :
719 [ # # ]: 0 : for (i = 0; i < list->num; i++) {
720 : 0 : struct wpa_freq_range *range = &list->range[i];
721 : :
722 [ # # ]: 0 : if (range->min == range->max)
723 [ # # ]: 0 : res = os_snprintf(pos, end - pos, "%s%u",
724 : : i == 0 ? "" : ",", range->min);
725 : : else
726 [ # # ]: 0 : res = os_snprintf(pos, end - pos, "%s%u-%u",
727 : : i == 0 ? "" : ",",
728 : : range->min, range->max);
729 [ # # ][ # # ]: 0 : if (res < 0 || res > end - pos) {
730 : 0 : os_free(buf);
731 : 0 : return NULL;
732 : : }
733 : 0 : pos += res;
734 : : }
735 : :
736 : 0 : return buf;
737 : : }
738 : :
739 : :
740 : 0 : int int_array_len(const int *a)
741 : : {
742 : : int i;
743 [ # # ][ # # ]: 0 : for (i = 0; a && a[i]; i++)
744 : : ;
745 : 0 : return i;
746 : : }
747 : :
748 : :
749 : 0 : void int_array_concat(int **res, const int *a)
750 : : {
751 : : int reslen, alen, i;
752 : : int *n;
753 : :
754 : 0 : reslen = int_array_len(*res);
755 : 0 : alen = int_array_len(a);
756 : :
757 : 0 : n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
758 [ # # ]: 0 : if (n == NULL) {
759 : 0 : os_free(*res);
760 : 0 : *res = NULL;
761 : 0 : return;
762 : : }
763 [ # # ]: 0 : for (i = 0; i <= alen; i++)
764 : 0 : n[reslen + i] = a[i];
765 : 0 : *res = n;
766 : : }
767 : :
768 : :
769 : 0 : static int freq_cmp(const void *a, const void *b)
770 : : {
771 : 0 : int _a = *(int *) a;
772 : 0 : int _b = *(int *) b;
773 : :
774 [ # # ]: 0 : if (_a == 0)
775 : 0 : return 1;
776 [ # # ]: 0 : if (_b == 0)
777 : 0 : return -1;
778 : 0 : return _a - _b;
779 : : }
780 : :
781 : :
782 : 0 : void int_array_sort_unique(int *a)
783 : : {
784 : : int alen;
785 : : int i, j;
786 : :
787 [ # # ]: 0 : if (a == NULL)
788 : 0 : return;
789 : :
790 : 0 : alen = int_array_len(a);
791 : 0 : qsort(a, alen, sizeof(int), freq_cmp);
792 : :
793 : 0 : i = 0;
794 : 0 : j = 1;
795 [ # # ][ # # ]: 0 : while (a[i] && a[j]) {
796 [ # # ]: 0 : if (a[i] == a[j]) {
797 : 0 : j++;
798 : 0 : continue;
799 : : }
800 : 0 : a[++i] = a[j++];
801 : : }
802 [ # # ]: 0 : if (a[i])
803 : 0 : i++;
804 : 0 : a[i] = 0;
805 : : }
806 : :
807 : :
808 : 0 : void int_array_add_unique(int **res, int a)
809 : : {
810 : : int reslen;
811 : : int *n;
812 : :
813 [ # # ][ # # ]: 0 : for (reslen = 0; *res && (*res)[reslen]; reslen++) {
814 [ # # ]: 0 : if ((*res)[reslen] == a)
815 : 0 : return; /* already in the list */
816 : : }
817 : :
818 : 0 : n = os_realloc_array(*res, reslen + 2, sizeof(int));
819 [ # # ]: 0 : if (n == NULL) {
820 : 0 : os_free(*res);
821 : 0 : *res = NULL;
822 : 0 : return;
823 : : }
824 : :
825 : 0 : n[reslen] = a;
826 : 0 : n[reslen + 1] = 0;
827 : :
828 : 0 : *res = n;
829 : : }
|