LCOV - code coverage report
Current view: top level - src/utils - common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 317 365 86.8 %
Date: 2014-05-28 Functions: 27 28 96.4 %

          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      169863 : static int hex2num(char c)
      15             : {
      16      169863 :         if (c >= '0' && c <= '9')
      17      143345 :                 return c - '0';
      18       26518 :         if (c >= 'a' && c <= 'f')
      19       20650 :                 return c - 'a' + 10;
      20        5868 :         if (c >= 'A' && c <= 'F')
      21        5801 :                 return c - 'A' + 10;
      22          67 :         return -1;
      23             : }
      24             : 
      25             : 
      26       63783 : int hex2byte(const char *hex)
      27             : {
      28             :         int a, b;
      29       63783 :         a = hex2num(*hex++);
      30       63783 :         if (a < 0)
      31          16 :                 return -1;
      32       63767 :         b = hex2num(*hex++);
      33       63767 :         if (b < 0)
      34          23 :                 return -1;
      35       63744 :         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        1548 : int hwaddr_aton(const char *txt, u8 *addr)
      46             : {
      47             :         int i;
      48             : 
      49       10660 :         for (i = 0; i < 6; i++) {
      50             :                 int a, b;
      51             : 
      52        9160 :                 a = hex2num(*txt++);
      53        9160 :                 if (a < 0)
      54          21 :                         return -1;
      55        9139 :                 b = hex2num(*txt++);
      56        9139 :                 if (b < 0)
      57           4 :                         return -1;
      58        9135 :                 *addr++ = (a << 4) | b;
      59        9135 :                 if (i < 5 && *txt++ != ':')
      60          23 :                         return -1;
      61             :         }
      62             : 
      63        1500 :         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        2003 : int hwaddr_aton2(const char *txt, u8 *addr)
      98             : {
      99             :         int i;
     100        2003 :         const char *pos = txt;
     101             : 
     102       14008 :         for (i = 0; i < 6; i++) {
     103             :                 int a, b;
     104             : 
     105       34010 :                 while (*pos == ':' || *pos == '.' || *pos == '-')
     106        9994 :                         pos++;
     107             : 
     108       12008 :                 a = hex2num(*pos++);
     109       12008 :                 if (a < 0)
     110           2 :                         return -1;
     111       12006 :                 b = hex2num(*pos++);
     112       12006 :                 if (b < 0)
     113           1 :                         return -1;
     114       12005 :                 *addr++ = (a << 4) | b;
     115             :         }
     116             : 
     117        2000 :         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        3823 : int hexstr2bin(const char *hex, u8 *buf, size_t len)
     130             : {
     131             :         size_t i;
     132             :         int a;
     133        3823 :         const char *ipos = hex;
     134        3823 :         u8 *opos = buf;
     135             : 
     136       67513 :         for (i = 0; i < len; i++) {
     137       63729 :                 a = hex2byte(ipos);
     138       63729 :                 if (a < 0)
     139          39 :                         return -1;
     140       63690 :                 *opos++ = a;
     141       63690 :                 ipos += 2;
     142             :         }
     143        3784 :         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        2522 : void inc_byte_array(u8 *counter, size_t len)
     157             : {
     158        2522 :         int pos = len - 1;
     159        5045 :         while (pos >= 0) {
     160        2523 :                 counter[pos]++;
     161        2523 :                 if (counter[pos] != 0)
     162        2522 :                         break;
     163           1 :                 pos--;
     164             :         }
     165        2522 : }
     166             : 
     167             : 
     168        2088 : 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        2088 :         os_get_time(&now);
     176        2088 :         sec = now.sec + 2208988800U; /* Epoch to 1900 */
     177             :         /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
     178        2088 :         usec = now.usec;
     179        2088 :         usec = 4295 * usec - (usec >> 5) - (usec >> 9);
     180        2088 :         tmp = host_to_be32(sec);
     181        2088 :         os_memcpy(buf, (u8 *) &tmp, 4);
     182        2088 :         tmp = host_to_be32(usec);
     183        2088 :         os_memcpy(buf + 4, (u8 *) &tmp, 4);
     184        2088 : }
     185             : 
     186             : 
     187       37514 : 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       37514 :         char *pos = buf, *end = buf + buf_size;
     192             :         int ret;
     193       37514 :         if (buf_size == 0)
     194           0 :                 return 0;
     195     1283606 :         for (i = 0; i < len; i++) {
     196     1246092 :                 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
     197     1246092 :                                   data[i]);
     198     1246092 :                 if (ret < 0 || ret >= end - pos) {
     199           0 :                         end[-1] = '\0';
     200           0 :                         return pos - buf;
     201             :                 }
     202     1246092 :                 pos += ret;
     203             :         }
     204       37514 :         end[-1] = '\0';
     205       37514 :         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       37293 : int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
     217             : {
     218       37293 :         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         221 : int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
     231             :                                size_t len)
     232             : {
     233         221 :         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       83780 : void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
     348             : {
     349       83780 :         char *end = txt + maxlen;
     350             :         size_t i;
     351             : 
     352     1604132 :         for (i = 0; i < len; i++) {
     353     1520353 :                 if (txt + 4 > end)
     354           1 :                         break;
     355             : 
     356     1520352 :                 switch (data[i]) {
     357             :                 case '\"':
     358           1 :                         *txt++ = '\\';
     359           1 :                         *txt++ = '\"';
     360           1 :                         break;
     361             :                 case '\\':
     362          35 :                         *txt++ = '\\';
     363          35 :                         *txt++ = '\\';
     364          35 :                         break;
     365             :                 case '\e':
     366           1 :                         *txt++ = '\\';
     367           1 :                         *txt++ = 'e';
     368           1 :                         break;
     369             :                 case '\n':
     370          25 :                         *txt++ = '\\';
     371          25 :                         *txt++ = 'n';
     372          25 :                         break;
     373             :                 case '\r':
     374           1 :                         *txt++ = '\\';
     375           1 :                         *txt++ = 'r';
     376           1 :                         break;
     377             :                 case '\t':
     378           1 :                         *txt++ = '\\';
     379           1 :                         *txt++ = 't';
     380           1 :                         break;
     381             :                 default:
     382     1520288 :                         if (data[i] >= 32 && data[i] <= 127) {
     383     1468970 :                                 *txt++ = data[i];
     384             :                         } else {
     385       51318 :                                 txt += os_snprintf(txt, end - txt, "\\x%02x",
     386       51318 :                                                    data[i]);
     387             :                         }
     388     1520288 :                         break;
     389             :                 }
     390             :         }
     391             : 
     392       83780 :         *txt = '\0';
     393       83780 : }
     394             : 
     395             : 
     396          19 : size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
     397             : {
     398          19 :         const char *pos = str;
     399          19 :         size_t len = 0;
     400             :         int val;
     401             : 
     402         211 :         while (*pos) {
     403         173 :                 if (len + 1 >= maxlen)
     404           0 :                         break;
     405         173 :                 switch (*pos) {
     406             :                 case '\\':
     407          88 :                         pos++;
     408          88 :                         switch (*pos) {
     409             :                         case '\\':
     410           2 :                                 buf[len++] = '\\';
     411           2 :                                 pos++;
     412           2 :                                 break;
     413             :                         case '"':
     414           2 :                                 buf[len++] = '"';
     415           2 :                                 pos++;
     416           2 :                                 break;
     417             :                         case 'n':
     418           8 :                                 buf[len++] = '\n';
     419           8 :                                 pos++;
     420           8 :                                 break;
     421             :                         case 'r':
     422           2 :                                 buf[len++] = '\r';
     423           2 :                                 pos++;
     424           2 :                                 break;
     425             :                         case 't':
     426           2 :                                 buf[len++] = '\t';
     427           2 :                                 pos++;
     428           2 :                                 break;
     429             :                         case 'e':
     430           2 :                                 buf[len++] = '\e';
     431           2 :                                 pos++;
     432           2 :                                 break;
     433             :                         case 'x':
     434          54 :                                 pos++;
     435          54 :                                 val = hex2byte(pos);
     436          54 :                                 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          54 :                                         buf[len++] = val;
     444          54 :                                         pos += 2;
     445             :                                 }
     446          54 :                                 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          16 :                                 val = *pos++ - '0';
     456          16 :                                 if (*pos >= '0' && *pos <= '7')
     457          13 :                                         val = val * 8 + (*pos++ - '0');
     458          16 :                                 if (*pos >= '0' && *pos <= '7')
     459          13 :                                         val = val * 8 + (*pos++ - '0');
     460          16 :                                 buf[len++] = val;
     461          16 :                                 break;
     462             :                         default:
     463           0 :                                 break;
     464             :                         }
     465          88 :                         break;
     466             :                 default:
     467          85 :                         buf[len++] = *pos++;
     468          85 :                         break;
     469             :                 }
     470             :         }
     471          19 :         if (maxlen > len)
     472          19 :                 buf[len] = '\0';
     473             : 
     474          19 :         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       12776 : const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
     493             : {
     494             :         static char ssid_txt[32 * 4 + 1];
     495             : 
     496       12776 :         if (ssid == NULL) {
     497           1 :                 ssid_txt[0] = '\0';
     498           1 :                 return ssid_txt;
     499             :         }
     500             : 
     501       12775 :         printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
     502       12775 :         return ssid_txt;
     503             : }
     504             : 
     505             : 
     506        7771 : void * __hide_aliasing_typecast(void *foo)
     507             : {
     508        7771 :         return foo;
     509             : }
     510             : 
     511             : 
     512        2533 : char * wpa_config_parse_string(const char *value, size_t *len)
     513             : {
     514        2533 :         if (*value == '"') {
     515             :                 const char *pos;
     516             :                 char *str;
     517        2414 :                 value++;
     518        2414 :                 pos = os_strrchr(value, '"');
     519        2414 :                 if (pos == NULL || pos[1] != '\0')
     520           2 :                         return NULL;
     521        2412 :                 *len = pos - value;
     522        2412 :                 str = dup_binstr(value, *len);
     523        2412 :                 if (str == NULL)
     524           0 :                         return NULL;
     525        2412 :                 return str;
     526         119 :         } else if (*value == 'P' && value[1] == '"') {
     527             :                 const char *pos;
     528             :                 char *tstr, *str;
     529             :                 size_t tlen;
     530           8 :                 value += 2;
     531           8 :                 pos = os_strrchr(value, '"');
     532           8 :                 if (pos == NULL || pos[1] != '\0')
     533           3 :                         return NULL;
     534           5 :                 tlen = pos - value;
     535           5 :                 tstr = dup_binstr(value, tlen);
     536           5 :                 if (tstr == NULL)
     537           0 :                         return NULL;
     538             : 
     539           5 :                 str = os_malloc(tlen + 1);
     540           5 :                 if (str == NULL) {
     541           0 :                         os_free(tstr);
     542           0 :                         return NULL;
     543             :                 }
     544             : 
     545           5 :                 *len = printf_decode((u8 *) str, tlen + 1, tstr);
     546           5 :                 os_free(tstr);
     547             : 
     548           5 :                 return str;
     549             :         } else {
     550             :                 u8 *str;
     551         111 :                 size_t tlen, hlen = os_strlen(value);
     552         111 :                 if (hlen & 1)
     553           3 :                         return NULL;
     554         108 :                 tlen = hlen / 2;
     555         108 :                 str = os_malloc(tlen + 1);
     556         108 :                 if (str == NULL)
     557           0 :                         return NULL;
     558         108 :                 if (hexstr2bin(value, str, tlen)) {
     559           2 :                         os_free(str);
     560           2 :                         return NULL;
     561             :                 }
     562         106 :                 str[tlen] = '\0';
     563         106 :                 *len = tlen;
     564         106 :                 return (char *) str;
     565             :         }
     566             : }
     567             : 
     568             : 
     569          14 : int is_hex(const u8 *data, size_t len)
     570             : {
     571             :         size_t i;
     572             : 
     573          59 :         for (i = 0; i < len; i++) {
     574          50 :                 if (data[i] < 32 || data[i] >= 127)
     575           5 :                         return 1;
     576             :         }
     577           9 :         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        2929 : 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        2929 :         size_t len = 0;
     601             : 
     602        2929 :         os_memset(res, 0, res_len);
     603             : 
     604        2929 :         if (src1) {
     605        2929 :                 if (src1_len >= res_len) {
     606           0 :                         os_memcpy(res, src1, res_len);
     607           0 :                         return res_len;
     608             :                 }
     609             : 
     610        2929 :                 os_memcpy(res, src1, src1_len);
     611        2929 :                 len += src1_len;
     612             :         }
     613             : 
     614        2929 :         if (src2) {
     615        2421 :                 if (len + src2_len >= res_len) {
     616           0 :                         os_memcpy(res + len, src2, res_len - len);
     617           0 :                         return res_len;
     618             :                 }
     619             : 
     620        2421 :                 os_memcpy(res + len, src2, src2_len);
     621        2421 :                 len += src2_len;
     622             :         }
     623             : 
     624        2929 :         return len;
     625             : }
     626             : 
     627             : 
     628        5810 : char * dup_binstr(const void *src, size_t len)
     629             : {
     630             :         char *res;
     631             : 
     632        5810 :         if (src == NULL)
     633           0 :                 return NULL;
     634        5810 :         res = os_malloc(len + 1);
     635        5810 :         if (res == NULL)
     636           0 :                 return NULL;
     637        5810 :         os_memcpy(res, src, len);
     638        5810 :         res[len] = '\0';
     639             : 
     640        5810 :         return res;
     641             : }
     642             : 
     643             : 
     644        2176 : int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value)
     645             : {
     646        2176 :         struct wpa_freq_range *freq = NULL, *n;
     647        2176 :         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        2176 :         pos = value;
     655        4644 :         while (pos && pos[0]) {
     656         292 :                 n = os_realloc_array(freq, count + 1,
     657             :                                      sizeof(struct wpa_freq_range));
     658         292 :                 if (n == NULL) {
     659           0 :                         os_free(freq);
     660           0 :                         return -1;
     661             :                 }
     662         292 :                 freq = n;
     663         292 :                 freq[count].min = atoi(pos);
     664         292 :                 pos2 = os_strchr(pos, '-');
     665         292 :                 pos3 = os_strchr(pos, ',');
     666         292 :                 if (pos2 && (!pos3 || pos2 < pos3)) {
     667          15 :                         pos2++;
     668          15 :                         freq[count].max = atoi(pos2);
     669             :                 } else
     670         277 :                         freq[count].max = freq[count].min;
     671         292 :                 pos = pos3;
     672         292 :                 if (pos)
     673          17 :                         pos++;
     674         292 :                 count++;
     675             :         }
     676             : 
     677        2176 :         os_free(res->range);
     678        2176 :         res->range = freq;
     679        2176 :         res->num = count;
     680             : 
     681        2176 :         return 0;
     682             : }
     683             : 
     684             : 
     685      535743 : int freq_range_list_includes(const struct wpa_freq_range_list *list,
     686             :                              unsigned int freq)
     687             : {
     688             :         unsigned int i;
     689             : 
     690      535743 :         if (list == NULL)
     691           0 :                 return 0;
     692             : 
     693      546299 :         for (i = 0; i < list->num; i++) {
     694       12642 :                 if (freq >= list->range[i].min && freq <= list->range[i].max)
     695        2086 :                         return 1;
     696             :         }
     697             : 
     698      533657 :         return 0;
     699             : }
     700             : 
     701             : 
     702           2 : 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           2 :         if (list->num == 0)
     710           0 :                 return NULL;
     711             : 
     712           2 :         maxlen = list->num * 30;
     713           2 :         buf = os_malloc(maxlen);
     714           2 :         if (buf == NULL)
     715           0 :                 return NULL;
     716           2 :         pos = buf;
     717           2 :         end = buf + maxlen;
     718             : 
     719           7 :         for (i = 0; i < list->num; i++) {
     720           5 :                 struct wpa_freq_range *range = &list->range[i];
     721             : 
     722           5 :                 if (range->min == range->max)
     723           4 :                         res = os_snprintf(pos, end - pos, "%s%u",
     724             :                                           i == 0 ? "" : ",", range->min);
     725             :                 else
     726           1 :                         res = os_snprintf(pos, end - pos, "%s%u-%u",
     727             :                                           i == 0 ? "" : ",",
     728             :                                           range->min, range->max);
     729           5 :                 if (res < 0 || res > end - pos) {
     730           0 :                         os_free(buf);
     731           0 :                         return NULL;
     732             :                 }
     733           5 :                 pos += res;
     734             :         }
     735             : 
     736           2 :         return buf;
     737             : }
     738             : 
     739             : 
     740        2632 : int int_array_len(const int *a)
     741             : {
     742             :         int i;
     743        2632 :         for (i = 0; a && a[i]; i++)
     744             :                 ;
     745        2632 :         return i;
     746             : }
     747             : 
     748             : 
     749         536 : void int_array_concat(int **res, const int *a)
     750             : {
     751             :         int reslen, alen, i;
     752             :         int *n;
     753             : 
     754         536 :         reslen = int_array_len(*res);
     755         536 :         alen = int_array_len(a);
     756             : 
     757         536 :         n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
     758         536 :         if (n == NULL) {
     759           0 :                 os_free(*res);
     760           0 :                 *res = NULL;
     761         536 :                 return;
     762             :         }
     763        1608 :         for (i = 0; i <= alen; i++)
     764        1072 :                 n[reslen + i] = a[i];
     765         536 :         *res = n;
     766             : }
     767             : 
     768             : 
     769          17 : static int freq_cmp(const void *a, const void *b)
     770             : {
     771          17 :         int _a = *(int *) a;
     772          17 :         int _b = *(int *) b;
     773             : 
     774          17 :         if (_a == 0)
     775           0 :                 return 1;
     776          17 :         if (_b == 0)
     777           0 :                 return -1;
     778          17 :         return _a - _b;
     779             : }
     780             : 
     781             : 
     782        1022 : void int_array_sort_unique(int *a)
     783             : {
     784             :         int alen;
     785             :         int i, j;
     786             : 
     787        1022 :         if (a == NULL)
     788        1509 :                 return;
     789             : 
     790         535 :         alen = int_array_len(a);
     791         535 :         qsort(a, alen, sizeof(int), freq_cmp);
     792             : 
     793         535 :         i = 0;
     794         535 :         j = 1;
     795        1078 :         while (a[i] && a[j]) {
     796           8 :                 if (a[i] == a[j]) {
     797           4 :                         j++;
     798           4 :                         continue;
     799             :                 }
     800           4 :                 a[++i] = a[j++];
     801             :         }
     802         535 :         if (a[i])
     803         535 :                 i++;
     804         535 :         a[i] = 0;
     805             : }
     806             : 
     807             : 
     808         676 : void int_array_add_unique(int **res, int a)
     809             : {
     810             :         int reslen;
     811             :         int *n;
     812             : 
     813        1700 :         for (reslen = 0; *res && (*res)[reslen]; reslen++) {
     814        1355 :                 if ((*res)[reslen] == a)
     815         331 :                         return; /* already in the list */
     816             :         }
     817             : 
     818         345 :         n = os_realloc_array(*res, reslen + 2, sizeof(int));
     819         345 :         if (n == NULL) {
     820           0 :                 os_free(*res);
     821           0 :                 *res = NULL;
     822           0 :                 return;
     823             :         }
     824             : 
     825         345 :         n[reslen] = a;
     826         345 :         n[reslen + 1] = 0;
     827             : 
     828         345 :         *res = n;
     829             : }

Generated by: LCOV version 1.10