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 52571 : static int hex2num(char c)
15 : {
16 52571 : if (c >= '0' && c <= '9')
17 45158 : return c - '0';
18 7413 : if (c >= 'a' && c <= 'f')
19 6779 : return c - 'a' + 10;
20 634 : if (c >= 'A' && c <= 'F')
21 610 : return c - 'A' + 10;
22 24 : return -1;
23 : }
24 :
25 :
26 24070 : int hex2byte(const char *hex)
27 : {
28 : int a, b;
29 24070 : a = hex2num(*hex++);
30 24070 : if (a < 0)
31 4 : return -1;
32 24066 : b = hex2num(*hex++);
33 24066 : if (b < 0)
34 13 : return -1;
35 24053 : 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 371 : int hwaddr_aton(const char *txt, u8 *addr)
46 : {
47 : int i;
48 :
49 2554 : for (i = 0; i < 6; i++) {
50 : int a, b;
51 :
52 2200 : a = hex2num(*txt++);
53 2200 : if (a < 0)
54 3 : return -1;
55 2197 : b = hex2num(*txt++);
56 2197 : if (b < 0)
57 3 : return -1;
58 2194 : *addr++ = (a << 4) | b;
59 2194 : if (i < 5 && *txt++ != ':')
60 11 : return -1;
61 : }
62 :
63 354 : 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 4 : int hwaddr_aton2(const char *txt, u8 *addr)
98 : {
99 : int i;
100 4 : const char *pos = txt;
101 :
102 22 : for (i = 0; i < 6; i++) {
103 : int a, b;
104 :
105 53 : while (*pos == ':' || *pos == '.' || *pos == '-')
106 15 : pos++;
107 :
108 19 : a = hex2num(*pos++);
109 19 : if (a < 0)
110 0 : return -1;
111 19 : b = hex2num(*pos++);
112 19 : if (b < 0)
113 1 : return -1;
114 18 : *addr++ = (a << 4) | b;
115 : }
116 :
117 3 : 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 1674 : int hexstr2bin(const char *hex, u8 *buf, size_t len)
130 : {
131 : size_t i;
132 : int a;
133 1674 : const char *ipos = hex;
134 1674 : u8 *opos = buf;
135 :
136 25727 : for (i = 0; i < len; i++) {
137 24070 : a = hex2byte(ipos);
138 24070 : if (a < 0)
139 17 : return -1;
140 24053 : *opos++ = a;
141 24053 : ipos += 2;
142 : }
143 1657 : 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 2221 : void inc_byte_array(u8 *counter, size_t len)
157 : {
158 2221 : int pos = len - 1;
159 4447 : while (pos >= 0) {
160 2226 : counter[pos]++;
161 2226 : if (counter[pos] != 0)
162 2221 : break;
163 5 : pos--;
164 : }
165 2221 : }
166 :
167 :
168 1838 : 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 1838 : os_get_time(&now);
176 1838 : sec = now.sec + 2208988800U; /* Epoch to 1900 */
177 : /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
178 1838 : usec = now.usec;
179 1838 : usec = 4295 * usec - (usec >> 5) - (usec >> 9);
180 1838 : tmp = host_to_be32(sec);
181 1838 : os_memcpy(buf, (u8 *) &tmp, 4);
182 1838 : tmp = host_to_be32(usec);
183 1838 : os_memcpy(buf + 4, (u8 *) &tmp, 4);
184 1838 : }
185 :
186 :
187 26433 : 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 26433 : char *pos = buf, *end = buf + buf_size;
192 : int ret;
193 26433 : if (buf_size == 0)
194 0 : return 0;
195 734941 : for (i = 0; i < len; i++) {
196 708508 : ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
197 708508 : data[i]);
198 708508 : if (ret < 0 || ret >= end - pos) {
199 0 : end[-1] = '\0';
200 0 : return pos - buf;
201 : }
202 708508 : pos += ret;
203 : }
204 26433 : end[-1] = '\0';
205 26433 : 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 26410 : int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
217 : {
218 26410 : 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 23 : int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
231 : size_t len)
232 : {
233 23 : 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 16973 : void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
348 : {
349 16973 : char *end = txt + maxlen;
350 : size_t i;
351 :
352 300915 : for (i = 0; i < len; i++) {
353 283943 : if (txt + 4 >= end)
354 1 : break;
355 :
356 283942 : switch (data[i]) {
357 : case '\"':
358 0 : *txt++ = '\\';
359 0 : *txt++ = '\"';
360 0 : break;
361 : case '\\':
362 1 : *txt++ = '\\';
363 1 : *txt++ = '\\';
364 1 : break;
365 : case '\033':
366 0 : *txt++ = '\\';
367 0 : *txt++ = 'e';
368 0 : break;
369 : case '\n':
370 1 : *txt++ = '\\';
371 1 : *txt++ = 'n';
372 1 : 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 283940 : if (data[i] >= 32 && data[i] <= 127) {
383 283884 : *txt++ = data[i];
384 : } else {
385 56 : txt += os_snprintf(txt, end - txt, "\\x%02x",
386 56 : data[i]);
387 : }
388 283940 : break;
389 : }
390 : }
391 :
392 16973 : *txt = '\0';
393 16973 : }
394 :
395 :
396 2 : size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
397 : {
398 2 : const char *pos = str;
399 2 : size_t len = 0;
400 : int val;
401 :
402 32 : while (*pos) {
403 28 : if (len + 1 >= maxlen)
404 0 : break;
405 28 : switch (*pos) {
406 : case '\\':
407 2 : pos++;
408 2 : 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 1 : buf[len++] = '\n';
419 1 : pos++;
420 1 : 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++] = '\033';
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 1 : val = *pos++ - '0';
456 1 : if (*pos >= '0' && *pos <= '7')
457 0 : val = val * 8 + (*pos++ - '0');
458 1 : if (*pos >= '0' && *pos <= '7')
459 0 : val = val * 8 + (*pos++ - '0');
460 1 : buf[len++] = val;
461 1 : break;
462 : default:
463 0 : break;
464 : }
465 2 : break;
466 : default:
467 26 : buf[len++] = *pos++;
468 26 : break;
469 : }
470 : }
471 2 : if (maxlen > len)
472 2 : buf[len] = '\0';
473 :
474 2 : 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 3034 : const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
493 : {
494 : static char ssid_txt[32 * 4 + 1];
495 :
496 3034 : if (ssid == NULL) {
497 0 : ssid_txt[0] = '\0';
498 0 : return ssid_txt;
499 : }
500 :
501 3034 : printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
502 3034 : return ssid_txt;
503 : }
504 :
505 :
506 1926 : void * __hide_aliasing_typecast(void *foo)
507 : {
508 1926 : return foo;
509 : }
510 :
511 :
512 10 : char * wpa_config_parse_string(const char *value, size_t *len)
513 : {
514 10 : if (*value == '"') {
515 : const char *pos;
516 : char *str;
517 3 : value++;
518 3 : pos = os_strrchr(value, '"');
519 3 : if (pos == NULL || pos[1] != '\0')
520 0 : return NULL;
521 3 : *len = pos - value;
522 3 : str = dup_binstr(value, *len);
523 3 : if (str == NULL)
524 0 : return NULL;
525 3 : return str;
526 7 : } else if (*value == 'P' && value[1] == '"') {
527 : const char *pos;
528 : char *tstr, *str;
529 : size_t tlen;
530 4 : value += 2;
531 4 : pos = os_strrchr(value, '"');
532 4 : if (pos == NULL || pos[1] != '\0')
533 2 : return NULL;
534 2 : tlen = pos - value;
535 2 : tstr = dup_binstr(value, tlen);
536 2 : if (tstr == NULL)
537 0 : return NULL;
538 :
539 2 : str = os_malloc(tlen + 1);
540 2 : if (str == NULL) {
541 0 : os_free(tstr);
542 0 : return NULL;
543 : }
544 :
545 2 : *len = printf_decode((u8 *) str, tlen + 1, tstr);
546 2 : os_free(tstr);
547 :
548 2 : return str;
549 : } else {
550 : u8 *str;
551 3 : size_t tlen, hlen = os_strlen(value);
552 3 : if (hlen & 1)
553 1 : return NULL;
554 2 : tlen = hlen / 2;
555 2 : str = os_malloc(tlen + 1);
556 2 : if (str == NULL)
557 0 : return NULL;
558 2 : if (hexstr2bin(value, str, tlen)) {
559 0 : os_free(str);
560 0 : return NULL;
561 : }
562 2 : str[tlen] = '\0';
563 2 : *len = tlen;
564 2 : return (char *) str;
565 : }
566 : }
567 :
568 :
569 1 : int is_hex(const u8 *data, size_t len)
570 : {
571 : size_t i;
572 :
573 4 : for (i = 0; i < len; i++) {
574 3 : if (data[i] < 32 || data[i] >= 127)
575 0 : return 1;
576 : }
577 1 : return 0;
578 : }
579 :
580 :
581 1 : int find_first_bit(u32 value)
582 : {
583 1 : int pos = 0;
584 :
585 2 : while (value) {
586 1 : if (value & 0x1)
587 1 : return pos;
588 0 : value >>= 1;
589 0 : pos++;
590 : }
591 :
592 0 : return -1;
593 : }
594 :
595 :
596 3976 : 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 3976 : size_t len = 0;
601 :
602 3976 : os_memset(res, 0, res_len);
603 :
604 3976 : if (src1) {
605 3976 : if (src1_len >= res_len) {
606 0 : os_memcpy(res, src1, res_len);
607 0 : return res_len;
608 : }
609 :
610 3976 : os_memcpy(res, src1, src1_len);
611 3976 : len += src1_len;
612 : }
613 :
614 3976 : if (src2) {
615 3610 : if (len + src2_len >= res_len) {
616 0 : os_memcpy(res + len, src2, res_len - len);
617 0 : return res_len;
618 : }
619 :
620 3610 : os_memcpy(res + len, src2, src2_len);
621 3610 : len += src2_len;
622 : }
623 :
624 3976 : return len;
625 : }
626 :
627 :
628 1055 : char * dup_binstr(const void *src, size_t len)
629 : {
630 : char *res;
631 :
632 1055 : if (src == NULL)
633 0 : return NULL;
634 1055 : res = os_malloc(len + 1);
635 1055 : if (res == NULL)
636 0 : return NULL;
637 1055 : os_memcpy(res, src, len);
638 1055 : res[len] = '\0';
639 :
640 1055 : 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 : }
830 :
831 :
832 658 : void str_clear_free(char *str)
833 : {
834 658 : if (str) {
835 193 : size_t len = os_strlen(str);
836 193 : os_memset(str, 0, len);
837 193 : os_free(str);
838 : }
839 658 : }
840 :
841 :
842 9072 : void bin_clear_free(void *bin, size_t len)
843 : {
844 9072 : if (bin) {
845 1864 : os_memset(bin, 0, len);
846 1864 : os_free(bin);
847 : }
848 9072 : }
849 :
850 :
851 0 : int random_mac_addr(u8 *addr)
852 : {
853 0 : if (os_get_random(addr, ETH_ALEN) < 0)
854 0 : return -1;
855 0 : addr[0] &= 0xfe; /* unicast */
856 0 : addr[0] |= 0x02; /* locally administered */
857 0 : return 0;
858 : }
859 :
860 :
861 0 : int random_mac_addr_keep_oui(u8 *addr)
862 : {
863 0 : if (os_get_random(addr + 3, 3) < 0)
864 0 : return -1;
865 0 : addr[0] &= 0xfe; /* unicast */
866 0 : addr[0] |= 0x02; /* locally administered */
867 0 : return 0;
868 : }
|