LCOV - code coverage report
Current view: top level - hostapd - config_file.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 2100 2363 88.9 %
Date: 2016-10-02 Functions: 43 43 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / Configuration file parser
       3             :  * Copyright (c) 2003-2015, 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 "utils/includes.h"
      10             : #ifndef CONFIG_NATIVE_WINDOWS
      11             : #include <grp.h>
      12             : #endif /* CONFIG_NATIVE_WINDOWS */
      13             : 
      14             : #include "utils/common.h"
      15             : #include "utils/uuid.h"
      16             : #include "common/ieee802_11_defs.h"
      17             : #include "drivers/driver.h"
      18             : #include "eap_server/eap.h"
      19             : #include "radius/radius_client.h"
      20             : #include "ap/wpa_auth.h"
      21             : #include "ap/ap_config.h"
      22             : #include "config_file.h"
      23             : 
      24             : 
      25             : #ifndef CONFIG_NO_RADIUS
      26             : #ifdef EAP_SERVER
      27             : static struct hostapd_radius_attr *
      28             : hostapd_parse_radius_attr(const char *value);
      29             : #endif /* EAP_SERVER */
      30             : #endif /* CONFIG_NO_RADIUS */
      31             : 
      32             : 
      33             : #ifndef CONFIG_NO_VLAN
      34           6 : static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
      35             :                                          const char *fname)
      36             : {
      37             :         FILE *f;
      38             :         char buf[128], *pos, *pos2;
      39           6 :         int line = 0, vlan_id;
      40             :         struct hostapd_vlan *vlan;
      41             : 
      42           6 :         f = fopen(fname, "r");
      43           6 :         if (!f) {
      44           0 :                 wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname);
      45           0 :                 return -1;
      46             :         }
      47             : 
      48          24 :         while (fgets(buf, sizeof(buf), f)) {
      49          12 :                 line++;
      50             : 
      51          12 :                 if (buf[0] == '#')
      52           0 :                         continue;
      53          12 :                 pos = buf;
      54         137 :                 while (*pos != '\0') {
      55         125 :                         if (*pos == '\n') {
      56          12 :                                 *pos = '\0';
      57          12 :                                 break;
      58             :                         }
      59         113 :                         pos++;
      60             :                 }
      61          12 :                 if (buf[0] == '\0')
      62           0 :                         continue;
      63             : 
      64          12 :                 if (buf[0] == '*') {
      65           6 :                         vlan_id = VLAN_ID_WILDCARD;
      66           6 :                         pos = buf + 1;
      67             :                 } else {
      68           6 :                         vlan_id = strtol(buf, &pos, 10);
      69           6 :                         if (buf == pos || vlan_id < 1 ||
      70             :                             vlan_id > MAX_VLAN_ID) {
      71           0 :                                 wpa_printf(MSG_ERROR, "Invalid VLAN ID at "
      72             :                                            "line %d in '%s'", line, fname);
      73           0 :                                 fclose(f);
      74           0 :                                 return -1;
      75             :                         }
      76             :                 }
      77             : 
      78          36 :                 while (*pos == ' ' || *pos == '\t')
      79          12 :                         pos++;
      80          12 :                 pos2 = pos;
      81         113 :                 while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
      82          89 :                         pos2++;
      83          12 :                 *pos2 = '\0';
      84          12 :                 if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
      85           0 :                         wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
      86             :                                    "in '%s'", line, fname);
      87           0 :                         fclose(f);
      88           0 :                         return -1;
      89             :                 }
      90             : 
      91          12 :                 vlan = os_zalloc(sizeof(*vlan));
      92          12 :                 if (vlan == NULL) {
      93           0 :                         wpa_printf(MSG_ERROR, "Out of memory while reading "
      94             :                                    "VLAN interfaces from '%s'", fname);
      95           0 :                         fclose(f);
      96           0 :                         return -1;
      97             :                 }
      98             : 
      99          12 :                 vlan->vlan_id = vlan_id;
     100          12 :                 vlan->vlan_desc.untagged = vlan_id;
     101          12 :                 vlan->vlan_desc.notempty = !!vlan_id;
     102          12 :                 os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
     103          12 :                 vlan->next = bss->vlan;
     104          12 :                 bss->vlan = vlan;
     105             :         }
     106             : 
     107           6 :         fclose(f);
     108             : 
     109           6 :         return 0;
     110             : }
     111             : #endif /* CONFIG_NO_VLAN */
     112             : 
     113             : 
     114           6 : static int hostapd_acl_comp(const void *a, const void *b)
     115             : {
     116           6 :         const struct mac_acl_entry *aa = a;
     117           6 :         const struct mac_acl_entry *bb = b;
     118           6 :         return os_memcmp(aa->addr, bb->addr, sizeof(macaddr));
     119             : }
     120             : 
     121             : 
     122          10 : static int hostapd_config_read_maclist(const char *fname,
     123             :                                        struct mac_acl_entry **acl, int *num)
     124             : {
     125             :         FILE *f;
     126             :         char buf[128], *pos;
     127          10 :         int line = 0;
     128             :         u8 addr[ETH_ALEN];
     129             :         struct mac_acl_entry *newacl;
     130             :         int vlan_id;
     131             : 
     132          10 :         if (!fname)
     133           0 :                 return 0;
     134             : 
     135          10 :         f = fopen(fname, "r");
     136          10 :         if (!f) {
     137           0 :                 wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname);
     138           0 :                 return -1;
     139             :         }
     140             : 
     141          52 :         while (fgets(buf, sizeof(buf), f)) {
     142          32 :                 int i, rem = 0;
     143             : 
     144          32 :                 line++;
     145             : 
     146          32 :                 if (buf[0] == '#')
     147           0 :                         continue;
     148          32 :                 pos = buf;
     149         640 :                 while (*pos != '\0') {
     150         608 :                         if (*pos == '\n') {
     151          32 :                                 *pos = '\0';
     152          32 :                                 break;
     153             :                         }
     154         576 :                         pos++;
     155             :                 }
     156          32 :                 if (buf[0] == '\0')
     157           0 :                         continue;
     158          32 :                 pos = buf;
     159          32 :                 if (buf[0] == '-') {
     160           8 :                         rem = 1;
     161           8 :                         pos++;
     162             :                 }
     163             : 
     164          32 :                 if (hwaddr_aton(pos, addr)) {
     165           0 :                         wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
     166             :                                    "line %d in '%s'", pos, line, fname);
     167           0 :                         fclose(f);
     168           0 :                         return -1;
     169             :                 }
     170             : 
     171          32 :                 if (rem) {
     172           8 :                         i = 0;
     173          36 :                         while (i < *num) {
     174          20 :                                 if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) ==
     175             :                                     0) {
     176           8 :                                         os_remove_in_array(*acl, *num,
     177             :                                                            sizeof(**acl), i);
     178           8 :                                         (*num)--;
     179             :                                 } else
     180          12 :                                         i++;
     181             :                         }
     182           8 :                         continue;
     183             :                 }
     184          24 :                 vlan_id = 0;
     185          24 :                 pos = buf;
     186         456 :                 while (*pos != '\0' && *pos != ' ' && *pos != '\t')
     187         408 :                         pos++;
     188          60 :                 while (*pos == ' ' || *pos == '\t')
     189          12 :                         pos++;
     190          24 :                 if (*pos != '\0')
     191          12 :                         vlan_id = atoi(pos);
     192             : 
     193          24 :                 newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
     194          24 :                 if (newacl == NULL) {
     195           0 :                         wpa_printf(MSG_ERROR, "MAC list reallocation failed");
     196           0 :                         fclose(f);
     197           0 :                         return -1;
     198             :                 }
     199             : 
     200          24 :                 *acl = newacl;
     201          24 :                 os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
     202          24 :                 os_memset(&(*acl)[*num].vlan_id, 0,
     203             :                           sizeof((*acl)[*num].vlan_id));
     204          24 :                 (*acl)[*num].vlan_id.untagged = vlan_id;
     205          24 :                 (*acl)[*num].vlan_id.notempty = !!vlan_id;
     206          24 :                 (*num)++;
     207             :         }
     208             : 
     209          10 :         fclose(f);
     210             : 
     211          10 :         qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
     212             : 
     213          10 :         return 0;
     214             : }
     215             : 
     216             : 
     217             : #ifdef EAP_SERVER
     218         143 : static int hostapd_config_read_eap_user(const char *fname,
     219             :                                         struct hostapd_bss_config *conf)
     220             : {
     221             :         FILE *f;
     222             :         char buf[512], *pos, *start, *pos2;
     223         143 :         int line = 0, ret = 0, num_methods;
     224         143 :         struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
     225             : 
     226         143 :         if (!fname)
     227           0 :                 return 0;
     228             : 
     229         143 :         if (os_strncmp(fname, "sqlite:", 7) == 0) {
     230             : #ifdef CONFIG_SQLITE
     231           2 :                 os_free(conf->eap_user_sqlite);
     232           2 :                 conf->eap_user_sqlite = os_strdup(fname + 7);
     233           2 :                 return 0;
     234             : #else /* CONFIG_SQLITE */
     235             :                 wpa_printf(MSG_ERROR,
     236             :                            "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
     237             :                 return -1;
     238             : #endif /* CONFIG_SQLITE */
     239             :         }
     240             : 
     241         141 :         f = fopen(fname, "r");
     242         141 :         if (!f) {
     243           0 :                 wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname);
     244           0 :                 return -1;
     245             :         }
     246             : 
     247             :         /* Lines: "user" METHOD,METHOD2 "password" (password optional) */
     248       17846 :         while (fgets(buf, sizeof(buf), f)) {
     249       17564 :                 line++;
     250             : 
     251       17564 :                 if (buf[0] == '#')
     252           0 :                         continue;
     253       17564 :                 pos = buf;
     254      594509 :                 while (*pos != '\0') {
     255      576945 :                         if (*pos == '\n') {
     256       17564 :                                 *pos = '\0';
     257       17564 :                                 break;
     258             :                         }
     259      559381 :                         pos++;
     260             :                 }
     261       17564 :                 if (buf[0] == '\0')
     262        2881 :                         continue;
     263             : 
     264             : #ifndef CONFIG_NO_RADIUS
     265       14683 :                 if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
     266             :                         struct hostapd_radius_attr *attr, *a;
     267        3030 :                         attr = hostapd_parse_radius_attr(buf + 19);
     268        3030 :                         if (attr == NULL) {
     269           0 :                                 wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
     270             :                                            buf + 19);
     271           0 :                                 user = NULL; /* already in the BSS list */
     272           0 :                                 goto failed;
     273             :                         }
     274        3030 :                         if (user->accept_attr == NULL) {
     275        1652 :                                 user->accept_attr = attr;
     276             :                         } else {
     277        1378 :                                 a = user->accept_attr;
     278        3445 :                                 while (a->next)
     279         689 :                                         a = a->next;
     280        1378 :                                 a->next = attr;
     281             :                         }
     282        3030 :                         continue;
     283             :                 }
     284             : #endif /* CONFIG_NO_RADIUS */
     285             : 
     286       11653 :                 user = NULL;
     287             : 
     288       11653 :                 if (buf[0] != '"' && buf[0] != '*') {
     289           0 :                         wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in "
     290             :                                    "start) on line %d in '%s'", line, fname);
     291           0 :                         goto failed;
     292             :                 }
     293             : 
     294       11653 :                 user = os_zalloc(sizeof(*user));
     295       11653 :                 if (user == NULL) {
     296           0 :                         wpa_printf(MSG_ERROR, "EAP user allocation failed");
     297           0 :                         goto failed;
     298             :                 }
     299       11653 :                 user->force_version = -1;
     300             : 
     301       11653 :                 if (buf[0] == '*') {
     302         137 :                         pos = buf;
     303             :                 } else {
     304       11516 :                         pos = buf + 1;
     305       11516 :                         start = pos;
     306      173248 :                         while (*pos != '"' && *pos != '\0')
     307      150216 :                                 pos++;
     308       11516 :                         if (*pos == '\0') {
     309           0 :                                 wpa_printf(MSG_ERROR, "Invalid EAP identity "
     310             :                                            "(no \" in end) on line %d in '%s'",
     311             :                                            line, fname);
     312           0 :                                 goto failed;
     313             :                         }
     314             : 
     315       11516 :                         user->identity = os_malloc(pos - start);
     316       11516 :                         if (user->identity == NULL) {
     317           0 :                                 wpa_printf(MSG_ERROR, "Failed to allocate "
     318             :                                            "memory for EAP identity");
     319           0 :                                 goto failed;
     320             :                         }
     321       11516 :                         os_memcpy(user->identity, start, pos - start);
     322       11516 :                         user->identity_len = pos - start;
     323             : 
     324       11516 :                         if (pos[0] == '"' && pos[1] == '*') {
     325        2466 :                                 user->wildcard_prefix = 1;
     326        2466 :                                 pos++;
     327             :                         }
     328             :                 }
     329       11653 :                 pos++;
     330       38118 :                 while (*pos == ' ' || *pos == '\t')
     331       14812 :                         pos++;
     332             : 
     333       11653 :                 if (*pos == '\0') {
     334           0 :                         wpa_printf(MSG_ERROR, "No EAP method on line %d in "
     335             :                                    "'%s'", line, fname);
     336           0 :                         goto failed;
     337             :                 }
     338             : 
     339       11653 :                 start = pos;
     340       98817 :                 while (*pos != ' ' && *pos != '\t' && *pos != '\0')
     341       75511 :                         pos++;
     342       11653 :                 if (*pos == '\0') {
     343        3151 :                         pos = NULL;
     344             :                 } else {
     345        8502 :                         *pos = '\0';
     346        8502 :                         pos++;
     347             :                 }
     348       11653 :                 num_methods = 0;
     349       26046 :                 while (*start) {
     350       14393 :                         char *pos3 = os_strchr(start, ',');
     351       14393 :                         if (pos3) {
     352        2740 :                                 *pos3++ = '\0';
     353             :                         }
     354       14393 :                         user->methods[num_methods].method =
     355       14393 :                                 eap_server_get_type(
     356             :                                         start,
     357             :                                         &user->methods[num_methods].vendor);
     358       14393 :                         if (user->methods[num_methods].vendor ==
     359       13708 :                             EAP_VENDOR_IETF &&
     360       13708 :                             user->methods[num_methods].method == EAP_TYPE_NONE)
     361             :                         {
     362        2329 :                                 if (os_strcmp(start, "TTLS-PAP") == 0) {
     363         685 :                                         user->ttls_auth |= EAP_TTLS_AUTH_PAP;
     364         685 :                                         goto skip_eap;
     365             :                                 }
     366        1644 :                                 if (os_strcmp(start, "TTLS-CHAP") == 0) {
     367         137 :                                         user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
     368         137 :                                         goto skip_eap;
     369             :                                 }
     370        1507 :                                 if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
     371         137 :                                         user->ttls_auth |=
     372             :                                                 EAP_TTLS_AUTH_MSCHAP;
     373         137 :                                         goto skip_eap;
     374             :                                 }
     375        1370 :                                 if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
     376        1096 :                                         user->ttls_auth |=
     377             :                                                 EAP_TTLS_AUTH_MSCHAPV2;
     378        1096 :                                         goto skip_eap;
     379             :                                 }
     380         274 :                                 if (os_strcmp(start, "MACACL") == 0) {
     381         274 :                                         user->macacl = 1;
     382         274 :                                         goto skip_eap;
     383             :                                 }
     384           0 :                                 wpa_printf(MSG_ERROR, "Unsupported EAP type "
     385             :                                            "'%s' on line %d in '%s'",
     386             :                                            start, line, fname);
     387           0 :                                 goto failed;
     388             :                         }
     389             : 
     390       12064 :                         num_methods++;
     391       12064 :                         if (num_methods >= EAP_MAX_METHODS)
     392           0 :                                 break;
     393             :                 skip_eap:
     394       14393 :                         if (pos3 == NULL)
     395       11653 :                                 break;
     396        2740 :                         start = pos3;
     397             :                 }
     398       11653 :                 if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) {
     399           0 :                         wpa_printf(MSG_ERROR, "No EAP types configured on "
     400             :                                    "line %d in '%s'", line, fname);
     401           0 :                         goto failed;
     402             :                 }
     403             : 
     404       11653 :                 if (pos == NULL)
     405        3151 :                         goto done;
     406             : 
     407       18116 :                 while (*pos == ' ' || *pos == '\t')
     408        1112 :                         pos++;
     409        8502 :                 if (*pos == '\0')
     410           0 :                         goto done;
     411             : 
     412        8502 :                 if (os_strncmp(pos, "[ver=0]", 7) == 0) {
     413         137 :                         user->force_version = 0;
     414         137 :                         goto done;
     415             :                 }
     416             : 
     417        8365 :                 if (os_strncmp(pos, "[ver=1]", 7) == 0) {
     418         137 :                         user->force_version = 1;
     419         137 :                         goto done;
     420             :                 }
     421             : 
     422        8228 :                 if (os_strncmp(pos, "[2]", 3) == 0) {
     423        1507 :                         user->phase2 = 1;
     424        1507 :                         goto done;
     425             :                 }
     426             : 
     427        6721 :                 if (*pos == '"') {
     428        4658 :                         pos++;
     429        4658 :                         start = pos;
     430       80556 :                         while (*pos != '"' && *pos != '\0')
     431       71240 :                                 pos++;
     432        4658 :                         if (*pos == '\0') {
     433           0 :                                 wpa_printf(MSG_ERROR, "Invalid EAP password "
     434             :                                            "(no \" in end) on line %d in '%s'",
     435             :                                            line, fname);
     436           0 :                                 goto failed;
     437             :                         }
     438             : 
     439        4658 :                         user->password = os_malloc(pos - start);
     440        4658 :                         if (user->password == NULL) {
     441           0 :                                 wpa_printf(MSG_ERROR, "Failed to allocate "
     442             :                                            "memory for EAP password");
     443           0 :                                 goto failed;
     444             :                         }
     445        4658 :                         os_memcpy(user->password, start, pos - start);
     446        4658 :                         user->password_len = pos - start;
     447             : 
     448        4658 :                         pos++;
     449        2063 :                 } else if (os_strncmp(pos, "hash:", 5) == 0) {
     450         411 :                         pos += 5;
     451         411 :                         pos2 = pos;
     452       27400 :                         while (*pos2 != '\0' && *pos2 != ' ' &&
     453       26578 :                                *pos2 != '\t' && *pos2 != '#')
     454       13152 :                                 pos2++;
     455         411 :                         if (pos2 - pos != 32) {
     456           0 :                                 wpa_printf(MSG_ERROR, "Invalid password hash "
     457             :                                            "on line %d in '%s'", line, fname);
     458           0 :                                 goto failed;
     459             :                         }
     460         411 :                         user->password = os_malloc(16);
     461         411 :                         if (user->password == NULL) {
     462           0 :                                 wpa_printf(MSG_ERROR, "Failed to allocate "
     463             :                                            "memory for EAP password hash");
     464           0 :                                 goto failed;
     465             :                         }
     466         411 :                         if (hexstr2bin(pos, user->password, 16) < 0) {
     467           0 :                                 wpa_printf(MSG_ERROR, "Invalid hash password "
     468             :                                            "on line %d in '%s'", line, fname);
     469           0 :                                 goto failed;
     470             :                         }
     471         411 :                         user->password_len = 16;
     472         411 :                         user->password_hash = 1;
     473         411 :                         pos = pos2;
     474             :                 } else {
     475        1652 :                         pos2 = pos;
     476      126568 :                         while (*pos2 != '\0' && *pos2 != ' ' &&
     477      123264 :                                *pos2 != '\t' && *pos2 != '#')
     478       61632 :                                 pos2++;
     479        1652 :                         if ((pos2 - pos) & 1) {
     480           0 :                                 wpa_printf(MSG_ERROR, "Invalid hex password "
     481             :                                            "on line %d in '%s'", line, fname);
     482           0 :                                 goto failed;
     483             :                         }
     484        1652 :                         user->password = os_malloc((pos2 - pos) / 2);
     485        1652 :                         if (user->password == NULL) {
     486           0 :                                 wpa_printf(MSG_ERROR, "Failed to allocate "
     487             :                                            "memory for EAP password");
     488           0 :                                 goto failed;
     489             :                         }
     490        1652 :                         if (hexstr2bin(pos, user->password,
     491        1652 :                                        (pos2 - pos) / 2) < 0) {
     492           0 :                                 wpa_printf(MSG_ERROR, "Invalid hex password "
     493             :                                            "on line %d in '%s'", line, fname);
     494           0 :                                 goto failed;
     495             :                         }
     496        1652 :                         user->password_len = (pos2 - pos) / 2;
     497        1652 :                         pos = pos2;
     498             :                 }
     499             : 
     500       16319 :                 while (*pos == ' ' || *pos == '\t')
     501        2877 :                         pos++;
     502        6721 :                 if (os_strncmp(pos, "[2]", 3) == 0) {
     503        2877 :                         user->phase2 = 1;
     504             :                 }
     505             : 
     506             :         done:
     507       11653 :                 if (tail == NULL) {
     508         141 :                         tail = new_user = user;
     509             :                 } else {
     510       11512 :                         tail->next = user;
     511       11512 :                         tail = user;
     512             :                 }
     513       11653 :                 continue;
     514             : 
     515             :         failed:
     516           0 :                 if (user)
     517           0 :                         hostapd_config_free_eap_user(user);
     518           0 :                 ret = -1;
     519           0 :                 break;
     520             :         }
     521             : 
     522         141 :         fclose(f);
     523             : 
     524         141 :         if (ret == 0) {
     525         141 :                 user = conf->eap_user;
     526         626 :                 while (user) {
     527             :                         struct hostapd_eap_user *prev;
     528             : 
     529         344 :                         prev = user;
     530         344 :                         user = user->next;
     531         344 :                         hostapd_config_free_eap_user(prev);
     532             :                 }
     533         141 :                 conf->eap_user = new_user;
     534             :         }
     535             : 
     536         141 :         return ret;
     537             : }
     538             : #endif /* EAP_SERVER */
     539             : 
     540             : 
     541             : #ifndef CONFIG_NO_RADIUS
     542             : static int
     543         647 : hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
     544             :                                 int *num_server, const char *val, int def_port,
     545             :                                 struct hostapd_radius_server **curr_serv)
     546             : {
     547             :         struct hostapd_radius_server *nserv;
     548             :         int ret;
     549             :         static int server_index = 1;
     550             : 
     551         647 :         nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv));
     552         647 :         if (nserv == NULL)
     553           2 :                 return -1;
     554             : 
     555         645 :         *server = nserv;
     556         645 :         nserv = &nserv[*num_server];
     557         645 :         (*num_server)++;
     558         645 :         (*curr_serv) = nserv;
     559             : 
     560         645 :         os_memset(nserv, 0, sizeof(*nserv));
     561         645 :         nserv->port = def_port;
     562         645 :         ret = hostapd_parse_ip_addr(val, &nserv->addr);
     563         645 :         nserv->index = server_index++;
     564             : 
     565         645 :         return ret;
     566             : }
     567             : 
     568             : 
     569             : static struct hostapd_radius_attr *
     570        3036 : hostapd_parse_radius_attr(const char *value)
     571             : {
     572             :         const char *pos;
     573             :         char syntax;
     574             :         struct hostapd_radius_attr *attr;
     575             :         size_t len;
     576             : 
     577        3036 :         attr = os_zalloc(sizeof(*attr));
     578        3036 :         if (attr == NULL)
     579           0 :                 return NULL;
     580             : 
     581        3036 :         attr->type = atoi(value);
     582             : 
     583        3036 :         pos = os_strchr(value, ':');
     584        3036 :         if (pos == NULL) {
     585           0 :                 attr->val = wpabuf_alloc(1);
     586           0 :                 if (attr->val == NULL) {
     587           0 :                         os_free(attr);
     588           0 :                         return NULL;
     589             :                 }
     590           0 :                 wpabuf_put_u8(attr->val, 0);
     591           0 :                 return attr;
     592             :         }
     593             : 
     594        3036 :         pos++;
     595        3036 :         if (pos[0] == '\0' || pos[1] != ':') {
     596           2 :                 os_free(attr);
     597           2 :                 return NULL;
     598             :         }
     599        3034 :         syntax = *pos++;
     600        3034 :         pos++;
     601             : 
     602        3034 :         switch (syntax) {
     603             :         case 's':
     604         830 :                 attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
     605         830 :                 break;
     606             :         case 'x':
     607        1100 :                 len = os_strlen(pos);
     608        1100 :                 if (len & 1)
     609           0 :                         break;
     610        1100 :                 len /= 2;
     611        1100 :                 attr->val = wpabuf_alloc(len);
     612        1100 :                 if (attr->val == NULL)
     613           0 :                         break;
     614        1100 :                 if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
     615           0 :                         wpabuf_free(attr->val);
     616           0 :                         os_free(attr);
     617           0 :                         return NULL;
     618             :                 }
     619        1100 :                 break;
     620             :         case 'd':
     621        1104 :                 attr->val = wpabuf_alloc(4);
     622        1104 :                 if (attr->val)
     623        1104 :                         wpabuf_put_be32(attr->val, atoi(pos));
     624        1104 :                 break;
     625             :         default:
     626           0 :                 os_free(attr);
     627           0 :                 return NULL;
     628             :         }
     629             : 
     630        3034 :         if (attr->val == NULL) {
     631           0 :                 os_free(attr);
     632           0 :                 return NULL;
     633             :         }
     634             : 
     635        3034 :         return attr;
     636             : }
     637             : 
     638             : 
     639           4 : static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
     640             : {
     641             :         char *secret;
     642             : 
     643           4 :         secret = os_strchr(val, ' ');
     644           4 :         if (secret == NULL)
     645           1 :                 return -1;
     646             : 
     647           3 :         *secret++ = '\0';
     648             : 
     649           3 :         if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
     650           1 :                 return -1;
     651             : 
     652           2 :         os_free(bss->radius_das_shared_secret);
     653           2 :         bss->radius_das_shared_secret = (u8 *) os_strdup(secret);
     654           2 :         if (bss->radius_das_shared_secret == NULL)
     655           0 :                 return -1;
     656           2 :         bss->radius_das_shared_secret_len = os_strlen(secret);
     657             : 
     658           2 :         return 0;
     659             : }
     660             : #endif /* CONFIG_NO_RADIUS */
     661             : 
     662             : 
     663        1181 : static int hostapd_config_parse_key_mgmt(int line, const char *value)
     664             : {
     665        1181 :         int val = 0, last;
     666             :         char *start, *end, *buf;
     667             : 
     668        1181 :         buf = os_strdup(value);
     669        1181 :         if (buf == NULL)
     670           2 :                 return -1;
     671        1179 :         start = buf;
     672             : 
     673        2371 :         while (*start != '\0') {
     674        2395 :                 while (*start == ' ' || *start == '\t')
     675          11 :                         start++;
     676        1192 :                 if (*start == '\0')
     677           1 :                         break;
     678        1191 :                 end = start;
     679       10780 :                 while (*end != ' ' && *end != '\t' && *end != '\0')
     680        8398 :                         end++;
     681        1191 :                 last = *end == '\0';
     682        1191 :                 *end = '\0';
     683        1191 :                 if (os_strcmp(start, "WPA-PSK") == 0)
     684         425 :                         val |= WPA_KEY_MGMT_PSK;
     685         766 :                 else if (os_strcmp(start, "WPA-EAP") == 0)
     686         649 :                         val |= WPA_KEY_MGMT_IEEE8021X;
     687             : #ifdef CONFIG_IEEE80211R
     688         117 :                 else if (os_strcmp(start, "FT-PSK") == 0)
     689          50 :                         val |= WPA_KEY_MGMT_FT_PSK;
     690          67 :                 else if (os_strcmp(start, "FT-EAP") == 0)
     691           7 :                         val |= WPA_KEY_MGMT_FT_IEEE8021X;
     692             : #endif /* CONFIG_IEEE80211R */
     693             : #ifdef CONFIG_IEEE80211W
     694          60 :                 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
     695          18 :                         val |= WPA_KEY_MGMT_PSK_SHA256;
     696          42 :                 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
     697           3 :                         val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
     698             : #endif /* CONFIG_IEEE80211W */
     699             : #ifdef CONFIG_SAE
     700          39 :                 else if (os_strcmp(start, "SAE") == 0)
     701          24 :                         val |= WPA_KEY_MGMT_SAE;
     702          15 :                 else if (os_strcmp(start, "FT-SAE") == 0)
     703           5 :                         val |= WPA_KEY_MGMT_FT_SAE;
     704             : #endif /* CONFIG_SAE */
     705             : #ifdef CONFIG_SUITEB
     706          10 :                 else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
     707           4 :                         val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
     708             : #endif /* CONFIG_SUITEB */
     709             : #ifdef CONFIG_SUITEB192
     710           6 :                 else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
     711           4 :                         val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
     712             : #endif /* CONFIG_SUITEB192 */
     713             :                 else {
     714           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
     715             :                                    line, start);
     716           2 :                         os_free(buf);
     717           2 :                         return -1;
     718             :                 }
     719             : 
     720        1189 :                 if (last)
     721        1176 :                         break;
     722          13 :                 start = end + 1;
     723             :         }
     724             : 
     725        1177 :         os_free(buf);
     726        1177 :         if (val == 0) {
     727           1 :                 wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values "
     728             :                            "configured.", line);
     729           1 :                 return -1;
     730             :         }
     731             : 
     732        1176 :         return val;
     733             : }
     734             : 
     735             : 
     736        1188 : static int hostapd_config_parse_cipher(int line, const char *value)
     737             : {
     738        1188 :         int val = wpa_parse_cipher(value);
     739        1188 :         if (val < 0) {
     740           3 :                 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
     741             :                            line, value);
     742           3 :                 return -1;
     743             :         }
     744        1185 :         if (val == 0) {
     745           1 :                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
     746             :                            line);
     747           1 :                 return -1;
     748             :         }
     749        1184 :         return val;
     750             : }
     751             : 
     752             : 
     753          20 : static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
     754             :                                    char *val)
     755             : {
     756          20 :         size_t len = os_strlen(val);
     757             : 
     758          20 :         if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL)
     759           0 :                 return -1;
     760             : 
     761          20 :         if (val[0] == '"') {
     762          18 :                 if (len < 2 || val[len - 1] != '"')
     763           2 :                         return -1;
     764          16 :                 len -= 2;
     765          16 :                 wep->key[keyidx] = os_malloc(len);
     766          16 :                 if (wep->key[keyidx] == NULL)
     767           0 :                         return -1;
     768          16 :                 os_memcpy(wep->key[keyidx], val + 1, len);
     769          16 :                 wep->len[keyidx] = len;
     770             :         } else {
     771           2 :                 if (len & 1)
     772           1 :                         return -1;
     773           1 :                 len /= 2;
     774           1 :                 wep->key[keyidx] = os_malloc(len);
     775           1 :                 if (wep->key[keyidx] == NULL)
     776           0 :                         return -1;
     777           1 :                 wep->len[keyidx] = len;
     778           1 :                 if (hexstr2bin(val, wep->key[keyidx], len) < 0)
     779           1 :                         return -1;
     780             :         }
     781             : 
     782          16 :         wep->keys_set++;
     783             : 
     784          16 :         return 0;
     785             : }
     786             : 
     787             : 
     788           6 : static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
     789             : {
     790             :         char *pos;
     791             : 
     792             :         /* for backwards compatibility, translate ' ' in conf str to ',' */
     793           6 :         pos = val;
     794          21 :         while (pos) {
     795           9 :                 pos = os_strchr(pos, ' ');
     796           9 :                 if (pos)
     797           3 :                         *pos++ = ',';
     798             :         }
     799           6 :         if (freq_range_list_parse(&conf->acs_ch_list, val))
     800           0 :                 return -1;
     801             : 
     802           6 :         return 0;
     803             : }
     804             : 
     805             : 
     806          17 : static int hostapd_parse_intlist(int **int_list, char *val)
     807             : {
     808             :         int *list;
     809             :         int count;
     810             :         char *pos, *end;
     811             : 
     812          17 :         os_free(*int_list);
     813          17 :         *int_list = NULL;
     814             : 
     815          17 :         pos = val;
     816          17 :         count = 0;
     817         192 :         while (*pos != '\0') {
     818         158 :                 if (*pos == ' ')
     819          40 :                         count++;
     820         158 :                 pos++;
     821             :         }
     822             : 
     823          17 :         list = os_malloc(sizeof(int) * (count + 2));
     824          17 :         if (list == NULL)
     825           0 :                 return -1;
     826          17 :         pos = val;
     827          17 :         count = 0;
     828          74 :         while (*pos != '\0') {
     829          57 :                 end = os_strchr(pos, ' ');
     830          57 :                 if (end)
     831          40 :                         *end = '\0';
     832             : 
     833          57 :                 list[count++] = atoi(pos);
     834          57 :                 if (!end)
     835          17 :                         break;
     836          40 :                 pos = end + 1;
     837             :         }
     838          17 :         list[count] = -1;
     839             : 
     840          17 :         *int_list = list;
     841          17 :         return 0;
     842             : }
     843             : 
     844             : 
     845          12 : static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
     846             : {
     847             :         struct hostapd_bss_config **all, *bss;
     848             : 
     849          12 :         if (*ifname == '\0')
     850           0 :                 return -1;
     851             : 
     852          12 :         all = os_realloc_array(conf->bss, conf->num_bss + 1,
     853             :                                sizeof(struct hostapd_bss_config *));
     854          12 :         if (all == NULL) {
     855           0 :                 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
     856             :                            "multi-BSS entry");
     857           0 :                 return -1;
     858             :         }
     859          12 :         conf->bss = all;
     860             : 
     861          12 :         bss = os_zalloc(sizeof(*bss));
     862          12 :         if (bss == NULL)
     863           0 :                 return -1;
     864          12 :         bss->radius = os_zalloc(sizeof(*bss->radius));
     865          12 :         if (bss->radius == NULL) {
     866           0 :                 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
     867             :                            "multi-BSS RADIUS data");
     868           0 :                 os_free(bss);
     869           0 :                 return -1;
     870             :         }
     871             : 
     872          12 :         conf->bss[conf->num_bss++] = bss;
     873          12 :         conf->last_bss = bss;
     874             : 
     875          12 :         hostapd_config_defaults_bss(bss);
     876          12 :         os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
     877          12 :         os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
     878             : 
     879          12 :         return 0;
     880             : }
     881             : 
     882             : 
     883             : /* convert floats with one decimal place to value*10 int, i.e.,
     884             :  * "1.5" will return 15 */
     885           2 : static int hostapd_config_read_int10(const char *value)
     886             : {
     887             :         int i, d;
     888             :         char *pos;
     889             : 
     890           2 :         i = atoi(value);
     891           2 :         pos = os_strchr(value, '.');
     892           2 :         d = 0;
     893           2 :         if (pos) {
     894           1 :                 pos++;
     895           1 :                 if (*pos >= '0' && *pos <= '9')
     896           1 :                         d = *pos - '0';
     897             :         }
     898             : 
     899           2 :         return i * 10 + d;
     900             : }
     901             : 
     902             : 
     903           6 : static int valid_cw(int cw)
     904             : {
     905          12 :         return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
     906           4 :                 cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
     907           8 :                 cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
     908             :                 cw == 32767);
     909             : }
     910             : 
     911             : 
     912             : enum {
     913             :         IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
     914             :         IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
     915             :         IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
     916             :         IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
     917             : };
     918             : 
     919          13 : static int hostapd_config_tx_queue(struct hostapd_config *conf,
     920             :                                    const char *name, const char *val)
     921             : {
     922             :         int num;
     923             :         const char *pos;
     924             :         struct hostapd_tx_queue_params *queue;
     925             : 
     926             :         /* skip 'tx_queue_' prefix */
     927          13 :         pos = name + 9;
     928          25 :         if (os_strncmp(pos, "data", 4) == 0 &&
     929          24 :             pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
     930          12 :                 num = pos[4] - '0';
     931          12 :                 pos += 6;
     932           2 :         } else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
     933           1 :                    os_strncmp(pos, "beacon_", 7) == 0) {
     934           0 :                 wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
     935           0 :                 return 0;
     936             :         } else {
     937           1 :                 wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
     938           1 :                 return -1;
     939             :         }
     940             : 
     941          12 :         if (num >= NUM_TX_QUEUES) {
     942             :                 /* for backwards compatibility, do not trigger failure */
     943           0 :                 wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
     944           0 :                 return 0;
     945             :         }
     946             : 
     947          12 :         queue = &conf->tx_queue[num];
     948             : 
     949          12 :         if (os_strcmp(pos, "aifs") == 0) {
     950           3 :                 queue->aifs = atoi(val);
     951           3 :                 if (queue->aifs < 0 || queue->aifs > 255) {
     952           1 :                         wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
     953             :                                    queue->aifs);
     954           1 :                         return -1;
     955             :                 }
     956           9 :         } else if (os_strcmp(pos, "cwmin") == 0) {
     957           3 :                 queue->cwmin = atoi(val);
     958           3 :                 if (!valid_cw(queue->cwmin)) {
     959           1 :                         wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
     960             :                                    queue->cwmin);
     961           1 :                         return -1;
     962             :                 }
     963           6 :         } else if (os_strcmp(pos, "cwmax") == 0) {
     964           3 :                 queue->cwmax = atoi(val);
     965           3 :                 if (!valid_cw(queue->cwmax)) {
     966           1 :                         wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
     967             :                                    queue->cwmax);
     968           1 :                         return -1;
     969             :                 }
     970           3 :         } else if (os_strcmp(pos, "burst") == 0) {
     971           2 :                 queue->burst = hostapd_config_read_int10(val);
     972             :         } else {
     973           1 :                 wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
     974           1 :                 return -1;
     975             :         }
     976             : 
     977           8 :         return 0;
     978             : }
     979             : 
     980             : 
     981             : #ifdef CONFIG_IEEE80211R
     982         117 : static int add_r0kh(struct hostapd_bss_config *bss, char *value)
     983             : {
     984             :         struct ft_remote_r0kh *r0kh;
     985             :         char *pos, *next;
     986             : 
     987         117 :         r0kh = os_zalloc(sizeof(*r0kh));
     988         117 :         if (r0kh == NULL)
     989           0 :                 return -1;
     990             : 
     991             :         /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
     992         117 :         pos = value;
     993         117 :         next = os_strchr(pos, ' ');
     994         117 :         if (next)
     995         117 :                 *next++ = '\0';
     996         117 :         if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
     997           1 :                 wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos);
     998           1 :                 os_free(r0kh);
     999           1 :                 return -1;
    1000             :         }
    1001             : 
    1002         116 :         pos = next;
    1003         116 :         next = os_strchr(pos, ' ');
    1004         116 :         if (next)
    1005         116 :                 *next++ = '\0';
    1006         116 :         if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
    1007           1 :                 wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos);
    1008           1 :                 os_free(r0kh);
    1009           1 :                 return -1;
    1010             :         }
    1011         115 :         r0kh->id_len = next - pos - 1;
    1012         115 :         os_memcpy(r0kh->id, pos, r0kh->id_len);
    1013             : 
    1014         115 :         pos = next;
    1015         115 :         if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) {
    1016           1 :                 wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos);
    1017           1 :                 os_free(r0kh);
    1018           1 :                 return -1;
    1019             :         }
    1020             : 
    1021         114 :         r0kh->next = bss->r0kh_list;
    1022         114 :         bss->r0kh_list = r0kh;
    1023             : 
    1024         114 :         return 0;
    1025             : }
    1026             : 
    1027             : 
    1028          60 : static int add_r1kh(struct hostapd_bss_config *bss, char *value)
    1029             : {
    1030             :         struct ft_remote_r1kh *r1kh;
    1031             :         char *pos, *next;
    1032             : 
    1033          60 :         r1kh = os_zalloc(sizeof(*r1kh));
    1034          60 :         if (r1kh == NULL)
    1035           0 :                 return -1;
    1036             : 
    1037             :         /* 02:01:02:03:04:05 02:01:02:03:04:05
    1038             :          * 000102030405060708090a0b0c0d0e0f */
    1039          60 :         pos = value;
    1040          60 :         next = os_strchr(pos, ' ');
    1041          60 :         if (next)
    1042          60 :                 *next++ = '\0';
    1043          60 :         if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
    1044           1 :                 wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos);
    1045           1 :                 os_free(r1kh);
    1046           1 :                 return -1;
    1047             :         }
    1048             : 
    1049          59 :         pos = next;
    1050          59 :         next = os_strchr(pos, ' ');
    1051          59 :         if (next)
    1052          59 :                 *next++ = '\0';
    1053          59 :         if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
    1054           1 :                 wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos);
    1055           1 :                 os_free(r1kh);
    1056           1 :                 return -1;
    1057             :         }
    1058             : 
    1059          58 :         pos = next;
    1060          58 :         if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) {
    1061           1 :                 wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos);
    1062           1 :                 os_free(r1kh);
    1063           1 :                 return -1;
    1064             :         }
    1065             : 
    1066          57 :         r1kh->next = bss->r1kh_list;
    1067          57 :         bss->r1kh_list = r1kh;
    1068             : 
    1069          57 :         return 0;
    1070             : }
    1071             : #endif /* CONFIG_IEEE80211R */
    1072             : 
    1073             : 
    1074             : #ifdef CONFIG_IEEE80211N
    1075          82 : static int hostapd_config_ht_capab(struct hostapd_config *conf,
    1076             :                                    const char *capab)
    1077             : {
    1078          82 :         if (os_strstr(capab, "[LDPC]"))
    1079           1 :                 conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
    1080          82 :         if (os_strstr(capab, "[HT40-]")) {
    1081          25 :                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
    1082          25 :                 conf->secondary_channel = -1;
    1083             :         }
    1084          82 :         if (os_strstr(capab, "[HT40+]")) {
    1085          50 :                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
    1086          50 :                 conf->secondary_channel = 1;
    1087             :         }
    1088          82 :         if (os_strstr(capab, "[SMPS-STATIC]")) {
    1089           2 :                 conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
    1090           2 :                 conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
    1091             :         }
    1092          82 :         if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
    1093           2 :                 conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
    1094           2 :                 conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
    1095             :         }
    1096          82 :         if (os_strstr(capab, "[GF]"))
    1097           1 :                 conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
    1098          82 :         if (os_strstr(capab, "[SHORT-GI-20]"))
    1099           1 :                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
    1100          82 :         if (os_strstr(capab, "[SHORT-GI-40]"))
    1101           3 :                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
    1102          82 :         if (os_strstr(capab, "[TX-STBC]"))
    1103           1 :                 conf->ht_capab |= HT_CAP_INFO_TX_STBC;
    1104          82 :         if (os_strstr(capab, "[RX-STBC1]")) {
    1105           1 :                 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
    1106           1 :                 conf->ht_capab |= HT_CAP_INFO_RX_STBC_1;
    1107             :         }
    1108          82 :         if (os_strstr(capab, "[RX-STBC12]")) {
    1109           1 :                 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
    1110           1 :                 conf->ht_capab |= HT_CAP_INFO_RX_STBC_12;
    1111             :         }
    1112          82 :         if (os_strstr(capab, "[RX-STBC123]")) {
    1113           1 :                 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
    1114           1 :                 conf->ht_capab |= HT_CAP_INFO_RX_STBC_123;
    1115             :         }
    1116          82 :         if (os_strstr(capab, "[DELAYED-BA]"))
    1117           1 :                 conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
    1118          82 :         if (os_strstr(capab, "[MAX-AMSDU-7935]"))
    1119           1 :                 conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
    1120          82 :         if (os_strstr(capab, "[DSSS_CCK-40]"))
    1121           1 :                 conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
    1122          82 :         if (os_strstr(capab, "[40-INTOLERANT]"))
    1123           3 :                 conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
    1124          82 :         if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
    1125           1 :                 conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
    1126             : 
    1127          82 :         return 0;
    1128             : }
    1129             : #endif /* CONFIG_IEEE80211N */
    1130             : 
    1131             : 
    1132             : #ifdef CONFIG_IEEE80211AC
    1133          16 : static int hostapd_config_vht_capab(struct hostapd_config *conf,
    1134             :                                     const char *capab)
    1135             : {
    1136          16 :         if (os_strstr(capab, "[MAX-MPDU-7991]"))
    1137           1 :                 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
    1138          16 :         if (os_strstr(capab, "[MAX-MPDU-11454]"))
    1139           3 :                 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
    1140          16 :         if (os_strstr(capab, "[VHT160]"))
    1141           1 :                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
    1142          16 :         if (os_strstr(capab, "[VHT160-80PLUS80]"))
    1143           1 :                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
    1144          16 :         if (os_strstr(capab, "[RXLDPC]"))
    1145           2 :                 conf->vht_capab |= VHT_CAP_RXLDPC;
    1146          16 :         if (os_strstr(capab, "[SHORT-GI-80]"))
    1147           2 :                 conf->vht_capab |= VHT_CAP_SHORT_GI_80;
    1148          16 :         if (os_strstr(capab, "[SHORT-GI-160]"))
    1149           1 :                 conf->vht_capab |= VHT_CAP_SHORT_GI_160;
    1150          16 :         if (os_strstr(capab, "[TX-STBC-2BY1]"))
    1151           2 :                 conf->vht_capab |= VHT_CAP_TXSTBC;
    1152          16 :         if (os_strstr(capab, "[RX-STBC-1]"))
    1153           2 :                 conf->vht_capab |= VHT_CAP_RXSTBC_1;
    1154          16 :         if (os_strstr(capab, "[RX-STBC-12]"))
    1155           1 :                 conf->vht_capab |= VHT_CAP_RXSTBC_2;
    1156          16 :         if (os_strstr(capab, "[RX-STBC-123]"))
    1157           1 :                 conf->vht_capab |= VHT_CAP_RXSTBC_3;
    1158          16 :         if (os_strstr(capab, "[RX-STBC-1234]"))
    1159           1 :                 conf->vht_capab |= VHT_CAP_RXSTBC_4;
    1160          16 :         if (os_strstr(capab, "[SU-BEAMFORMER]"))
    1161           1 :                 conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE;
    1162          16 :         if (os_strstr(capab, "[SU-BEAMFORMEE]"))
    1163           1 :                 conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE;
    1164          17 :         if (os_strstr(capab, "[BF-ANTENNA-2]") &&
    1165           1 :             (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
    1166           1 :                 conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
    1167          17 :         if (os_strstr(capab, "[BF-ANTENNA-3]") &&
    1168           1 :             (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
    1169           1 :                 conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
    1170          17 :         if (os_strstr(capab, "[BF-ANTENNA-4]") &&
    1171           1 :             (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
    1172           1 :                 conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
    1173          17 :         if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
    1174           1 :             (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
    1175           1 :                 conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
    1176          17 :         if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") &&
    1177           1 :             (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
    1178           1 :                 conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
    1179          17 :         if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") &&
    1180           1 :             (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
    1181           1 :                 conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
    1182          16 :         if (os_strstr(capab, "[MU-BEAMFORMER]"))
    1183           1 :                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
    1184          16 :         if (os_strstr(capab, "[VHT-TXOP-PS]"))
    1185           1 :                 conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
    1186          16 :         if (os_strstr(capab, "[HTC-VHT]"))
    1187           1 :                 conf->vht_capab |= VHT_CAP_HTC_VHT;
    1188          16 :         if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]"))
    1189           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
    1190          15 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]"))
    1191           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6;
    1192          14 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]"))
    1193           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5;
    1194          13 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]"))
    1195           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4;
    1196          12 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]"))
    1197           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3;
    1198          11 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]"))
    1199           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2;
    1200          10 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]"))
    1201           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1;
    1202          17 :         if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
    1203           1 :             (conf->vht_capab & VHT_CAP_HTC_VHT))
    1204           1 :                 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
    1205          17 :         if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
    1206           1 :             (conf->vht_capab & VHT_CAP_HTC_VHT))
    1207           1 :                 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
    1208          16 :         if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
    1209           1 :                 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
    1210          16 :         if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
    1211           1 :                 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
    1212          16 :         return 0;
    1213             : }
    1214             : #endif /* CONFIG_IEEE80211AC */
    1215             : 
    1216             : 
    1217             : #ifdef CONFIG_INTERWORKING
    1218         767 : static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
    1219             :                                     int line)
    1220             : {
    1221         767 :         size_t len = os_strlen(pos);
    1222             :         u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
    1223             : 
    1224             :         struct hostapd_roaming_consortium *rc;
    1225             : 
    1226        1531 :         if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
    1227         764 :             hexstr2bin(pos, oi, len / 2)) {
    1228           3 :                 wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
    1229             :                            "'%s'", line, pos);
    1230           3 :                 return -1;
    1231             :         }
    1232         764 :         len /= 2;
    1233             : 
    1234         764 :         rc = os_realloc_array(bss->roaming_consortium,
    1235         764 :                               bss->roaming_consortium_count + 1,
    1236             :                               sizeof(struct hostapd_roaming_consortium));
    1237         764 :         if (rc == NULL)
    1238           0 :                 return -1;
    1239             : 
    1240         764 :         os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
    1241         764 :         rc[bss->roaming_consortium_count].len = len;
    1242             : 
    1243         764 :         bss->roaming_consortium = rc;
    1244         764 :         bss->roaming_consortium_count++;
    1245             : 
    1246         764 :         return 0;
    1247             : }
    1248             : 
    1249             : 
    1250         515 : static int parse_lang_string(struct hostapd_lang_string **array,
    1251             :                              unsigned int *count, char *pos)
    1252             : {
    1253         515 :         char *sep, *str = NULL;
    1254             :         size_t clen, nlen, slen;
    1255             :         struct hostapd_lang_string *ls;
    1256         515 :         int ret = -1;
    1257             : 
    1258         515 :         if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) {
    1259           2 :                 str = wpa_config_parse_string(pos, &slen);
    1260           2 :                 if (!str)
    1261           1 :                         return -1;
    1262           1 :                 pos = str;
    1263             :         }
    1264             : 
    1265         514 :         sep = os_strchr(pos, ':');
    1266         514 :         if (sep == NULL)
    1267           2 :                 goto fail;
    1268         512 :         *sep++ = '\0';
    1269             : 
    1270         512 :         clen = os_strlen(pos);
    1271         512 :         if (clen < 2 || clen > sizeof(ls->lang))
    1272             :                 goto fail;
    1273         507 :         nlen = os_strlen(sep);
    1274         507 :         if (nlen > 252)
    1275           1 :                 goto fail;
    1276             : 
    1277         506 :         ls = os_realloc_array(*array, *count + 1,
    1278             :                               sizeof(struct hostapd_lang_string));
    1279         506 :         if (ls == NULL)
    1280           0 :                 goto fail;
    1281             : 
    1282         506 :         *array = ls;
    1283         506 :         ls = &(*array)[*count];
    1284         506 :         (*count)++;
    1285             : 
    1286         506 :         os_memset(ls->lang, 0, sizeof(ls->lang));
    1287         506 :         os_memcpy(ls->lang, pos, clen);
    1288         506 :         ls->name_len = nlen;
    1289         506 :         os_memcpy(ls->name, sep, nlen);
    1290             : 
    1291         506 :         ret = 0;
    1292             : fail:
    1293         514 :         os_free(str);
    1294         514 :         return ret;
    1295             : }
    1296             : 
    1297             : 
    1298         401 : static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
    1299             :                             int line)
    1300             : {
    1301         401 :         if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) {
    1302           6 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
    1303             :                            line, pos);
    1304           6 :                 return -1;
    1305             :         }
    1306         395 :         return 0;
    1307             : }
    1308             : 
    1309             : 
    1310         201 : static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
    1311             :                                int line)
    1312             : {
    1313             :         size_t count;
    1314             :         char *pos;
    1315         201 :         u8 *info = NULL, *ipos;
    1316             : 
    1317             :         /* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
    1318             : 
    1319         201 :         count = 1;
    1320        1557 :         for (pos = buf; *pos; pos++) {
    1321        1357 :                 if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',')
    1322           1 :                         goto fail;
    1323        1356 :                 if (*pos == ';')
    1324         133 :                         count++;
    1325             :         }
    1326         200 :         if (1 + count * 3 > 0x7f)
    1327           1 :                 goto fail;
    1328             : 
    1329         199 :         info = os_zalloc(2 + 3 + count * 3);
    1330         199 :         if (info == NULL)
    1331           0 :                 return -1;
    1332             : 
    1333         199 :         ipos = info;
    1334         199 :         *ipos++ = 0; /* GUD - Version 1 */
    1335         199 :         *ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
    1336         199 :         *ipos++ = 0; /* PLMN List IEI */
    1337             :         /* ext(b8) | Length of PLMN List value contents(b7..1) */
    1338         199 :         *ipos++ = 1 + count * 3;
    1339         199 :         *ipos++ = count; /* Number of PLMNs */
    1340             : 
    1341         199 :         pos = buf;
    1342         596 :         while (pos && *pos) {
    1343             :                 char *mcc, *mnc;
    1344             :                 size_t mnc_len;
    1345             : 
    1346         202 :                 mcc = pos;
    1347         202 :                 mnc = os_strchr(pos, ',');
    1348         202 :                 if (mnc == NULL)
    1349           1 :                         goto fail;
    1350         201 :                 *mnc++ = '\0';
    1351         201 :                 pos = os_strchr(mnc, ';');
    1352         201 :                 if (pos)
    1353           3 :                         *pos++ = '\0';
    1354             : 
    1355         201 :                 mnc_len = os_strlen(mnc);
    1356         201 :                 if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3))
    1357             :                         goto fail;
    1358             : 
    1359             :                 /* BC coded MCC,MNC */
    1360             :                 /* MCC digit 2 | MCC digit 1 */
    1361         198 :                 *ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
    1362             :                 /* MNC digit 3 | MCC digit 3 */
    1363         396 :                 *ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
    1364         198 :                         (mcc[2] - '0');
    1365             :                 /* MNC digit 2 | MNC digit 1 */
    1366         198 :                 *ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
    1367             :         }
    1368             : 
    1369         195 :         os_free(bss->anqp_3gpp_cell_net);
    1370         195 :         bss->anqp_3gpp_cell_net = info;
    1371         195 :         bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
    1372         390 :         wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
    1373         195 :                     bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
    1374             : 
    1375         195 :         return 0;
    1376             : 
    1377             : fail:
    1378           6 :         wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s",
    1379             :                    line, buf);
    1380           6 :         os_free(info);
    1381           6 :         return -1;
    1382             : }
    1383             : 
    1384             : 
    1385         357 : static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line)
    1386             : {
    1387             :         struct hostapd_nai_realm_data *realm;
    1388             :         size_t i, j, len;
    1389             :         int *offsets;
    1390             :         char *pos, *end, *rpos;
    1391             : 
    1392         357 :         offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS,
    1393             :                             sizeof(int));
    1394         357 :         if (offsets == NULL)
    1395           0 :                 return -1;
    1396             : 
    1397         513 :         for (i = 0; i < bss->nai_realm_count; i++) {
    1398         156 :                 realm = &bss->nai_realm_data[i];
    1399        1716 :                 for (j = 0; j < MAX_NAI_REALMS; j++) {
    1400        3280 :                         offsets[i * MAX_NAI_REALMS + j] =
    1401        1560 :                                 realm->realm[j] ?
    1402         160 :                                 realm->realm[j] - realm->realm_buf : -1;
    1403             :                 }
    1404             :         }
    1405             : 
    1406         357 :         realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1,
    1407             :                                  sizeof(struct hostapd_nai_realm_data));
    1408         357 :         if (realm == NULL) {
    1409           0 :                 os_free(offsets);
    1410           0 :                 return -1;
    1411             :         }
    1412         357 :         bss->nai_realm_data = realm;
    1413             : 
    1414             :         /* patch the pointers after realloc */
    1415         513 :         for (i = 0; i < bss->nai_realm_count; i++) {
    1416         156 :                 realm = &bss->nai_realm_data[i];
    1417        1716 :                 for (j = 0; j < MAX_NAI_REALMS; j++) {
    1418        1560 :                         int offs = offsets[i * MAX_NAI_REALMS + j];
    1419        1560 :                         if (offs >= 0)
    1420         160 :                                 realm->realm[j] = realm->realm_buf + offs;
    1421             :                         else
    1422        1400 :                                 realm->realm[j] = NULL;
    1423             :                 }
    1424             :         }
    1425         357 :         os_free(offsets);
    1426             : 
    1427         357 :         realm = &bss->nai_realm_data[bss->nai_realm_count];
    1428         357 :         os_memset(realm, 0, sizeof(*realm));
    1429             : 
    1430         357 :         pos = buf;
    1431         357 :         realm->encoding = atoi(pos);
    1432         357 :         pos = os_strchr(pos, ',');
    1433         357 :         if (pos == NULL)
    1434           1 :                 goto fail;
    1435         356 :         pos++;
    1436             : 
    1437         356 :         end = os_strchr(pos, ',');
    1438         356 :         if (end) {
    1439         202 :                 len = end - pos;
    1440         202 :                 *end = '\0';
    1441             :         } else {
    1442         154 :                 len = os_strlen(pos);
    1443             :         }
    1444             : 
    1445         356 :         if (len > MAX_NAI_REALMLEN) {
    1446           1 :                 wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d "
    1447             :                            "characters)", (int) len, MAX_NAI_REALMLEN);
    1448           1 :                 goto fail;
    1449             :         }
    1450         355 :         os_memcpy(realm->realm_buf, pos, len);
    1451             : 
    1452         355 :         if (end)
    1453         202 :                 pos = end + 1;
    1454             :         else
    1455         153 :                 pos = NULL;
    1456             : 
    1457         877 :         while (pos && *pos) {
    1458             :                 struct hostapd_nai_realm_eap *eap;
    1459             : 
    1460         369 :                 if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) {
    1461           1 :                         wpa_printf(MSG_ERROR, "Too many EAP methods");
    1462           1 :                         goto fail;
    1463             :                 }
    1464             : 
    1465         368 :                 eap = &realm->eap_method[realm->eap_method_count];
    1466         368 :                 realm->eap_method_count++;
    1467             : 
    1468         368 :                 end = os_strchr(pos, ',');
    1469         368 :                 if (end == NULL)
    1470         201 :                         end = pos + os_strlen(pos);
    1471             : 
    1472         368 :                 eap->eap_method = atoi(pos);
    1473             :                 for (;;) {
    1474         896 :                         pos = os_strchr(pos, '[');
    1475         896 :                         if (pos == NULL || pos > end)
    1476             :                                 break;
    1477         531 :                         pos++;
    1478         531 :                         if (eap->num_auths >= MAX_NAI_AUTH_TYPES) {
    1479           1 :                                 wpa_printf(MSG_ERROR, "Too many auth params");
    1480           1 :                                 goto fail;
    1481             :                         }
    1482         530 :                         eap->auth_id[eap->num_auths] = atoi(pos);
    1483         530 :                         pos = os_strchr(pos, ':');
    1484         530 :                         if (pos == NULL || pos > end)
    1485             :                                 goto fail;
    1486         529 :                         pos++;
    1487         529 :                         eap->auth_val[eap->num_auths] = atoi(pos);
    1488         529 :                         pos = os_strchr(pos, ']');
    1489         529 :                         if (pos == NULL || pos > end)
    1490             :                                 goto fail;
    1491         528 :                         pos++;
    1492         528 :                         eap->num_auths++;
    1493         528 :                 }
    1494             : 
    1495         365 :                 if (*end != ',')
    1496         198 :                         break;
    1497             : 
    1498         167 :                 pos = end + 1;
    1499             :         }
    1500             : 
    1501             :         /* Split realm list into null terminated realms */
    1502         351 :         rpos = realm->realm_buf;
    1503         351 :         i = 0;
    1504         716 :         while (*rpos) {
    1505         365 :                 if (i >= MAX_NAI_REALMS) {
    1506           1 :                         wpa_printf(MSG_ERROR, "Too many realms");
    1507           1 :                         goto fail;
    1508             :                 }
    1509         364 :                 realm->realm[i++] = rpos;
    1510         364 :                 rpos = os_strchr(rpos, ';');
    1511         364 :                 if (rpos == NULL)
    1512         350 :                         break;
    1513          14 :                 *rpos++ = '\0';
    1514             :         }
    1515             : 
    1516         350 :         bss->nai_realm_count++;
    1517             : 
    1518         350 :         return 0;
    1519             : 
    1520             : fail:
    1521           7 :         wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf);
    1522           7 :         return -1;
    1523             : }
    1524             : 
    1525             : 
    1526          34 : static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
    1527             : {
    1528             :         char *delim;
    1529             :         u16 infoid;
    1530             :         size_t len;
    1531             :         struct wpabuf *payload;
    1532             :         struct anqp_element *elem;
    1533             : 
    1534          34 :         delim = os_strchr(buf, ':');
    1535          34 :         if (!delim)
    1536           0 :                 return -1;
    1537          34 :         delim++;
    1538          34 :         infoid = atoi(buf);
    1539          34 :         len = os_strlen(delim);
    1540          34 :         if (len & 1)
    1541           0 :                 return -1;
    1542          34 :         len /= 2;
    1543          34 :         payload = wpabuf_alloc(len);
    1544          34 :         if (!payload)
    1545           0 :                 return -1;
    1546          34 :         if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) {
    1547           0 :                 wpabuf_free(payload);
    1548           0 :                 return -1;
    1549             :         }
    1550             : 
    1551          56 :         dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) {
    1552          46 :                 if (elem->infoid == infoid) {
    1553             :                         /* Update existing entry */
    1554          24 :                         wpabuf_free(elem->payload);
    1555          24 :                         elem->payload = payload;
    1556          24 :                         return 0;
    1557             :                 }
    1558             :         }
    1559             : 
    1560             :         /* Add a new entry */
    1561          10 :         elem = os_zalloc(sizeof(*elem));
    1562          10 :         if (!elem) {
    1563           0 :                 wpabuf_free(payload);
    1564           0 :                 return -1;
    1565             :         }
    1566          10 :         elem->infoid = infoid;
    1567          10 :         elem->payload = payload;
    1568          10 :         dl_list_add(&bss->anqp_elem, &elem->list);
    1569             : 
    1570          10 :         return 0;
    1571             : }
    1572             : 
    1573             : 
    1574           7 : static int parse_qos_map_set(struct hostapd_bss_config *bss,
    1575             :                              char *buf, int line)
    1576             : {
    1577           7 :         u8 qos_map_set[16 + 2 * 21], count = 0;
    1578           7 :         char *pos = buf;
    1579             :         int val;
    1580             : 
    1581             :         for (;;) {
    1582         143 :                 if (count == sizeof(qos_map_set)) {
    1583           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set "
    1584             :                                    "parameters '%s'", line, buf);
    1585           1 :                         return -1;
    1586             :                 }
    1587             : 
    1588         142 :                 val = atoi(pos);
    1589         142 :                 if (val > 255 || val < 0) {
    1590           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set "
    1591             :                                    "'%s'", line, buf);
    1592           2 :                         return -1;
    1593             :                 }
    1594             : 
    1595         140 :                 qos_map_set[count++] = val;
    1596         140 :                 pos = os_strchr(pos, ',');
    1597         140 :                 if (!pos)
    1598           4 :                         break;
    1599         136 :                 pos++;
    1600         136 :         }
    1601             : 
    1602           4 :         if (count < 16 || count & 1) {
    1603           3 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'",
    1604             :                            line, buf);
    1605           3 :                 return -1;
    1606             :         }
    1607             : 
    1608           1 :         os_memcpy(bss->qos_map_set, qos_map_set, count);
    1609           1 :         bss->qos_map_set_len = count;
    1610             : 
    1611           1 :         return 0;
    1612             : }
    1613             : 
    1614             : #endif /* CONFIG_INTERWORKING */
    1615             : 
    1616             : 
    1617             : #ifdef CONFIG_HS20
    1618         592 : static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
    1619             :                                  int line)
    1620             : {
    1621             :         u8 *conn_cap;
    1622             :         char *pos;
    1623             : 
    1624         592 :         if (bss->hs20_connection_capability_len >= 0xfff0)
    1625           0 :                 return -1;
    1626             : 
    1627         592 :         conn_cap = os_realloc(bss->hs20_connection_capability,
    1628         592 :                               bss->hs20_connection_capability_len + 4);
    1629         592 :         if (conn_cap == NULL)
    1630           0 :                 return -1;
    1631             : 
    1632         592 :         bss->hs20_connection_capability = conn_cap;
    1633         592 :         conn_cap += bss->hs20_connection_capability_len;
    1634         592 :         pos = buf;
    1635         592 :         conn_cap[0] = atoi(pos);
    1636         592 :         pos = os_strchr(pos, ':');
    1637         592 :         if (pos == NULL)
    1638           1 :                 return -1;
    1639         591 :         pos++;
    1640         591 :         WPA_PUT_LE16(conn_cap + 1, atoi(pos));
    1641         591 :         pos = os_strchr(pos, ':');
    1642         591 :         if (pos == NULL)
    1643           1 :                 return -1;
    1644         590 :         pos++;
    1645         590 :         conn_cap[3] = atoi(pos);
    1646         590 :         bss->hs20_connection_capability_len += 4;
    1647             : 
    1648         590 :         return 0;
    1649             : }
    1650             : 
    1651             : 
    1652         205 : static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf,
    1653             :                                   int line)
    1654             : {
    1655             :         u8 *wan_metrics;
    1656             :         char *pos;
    1657             : 
    1658             :         /* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */
    1659             : 
    1660         205 :         wan_metrics = os_zalloc(13);
    1661         205 :         if (wan_metrics == NULL)
    1662           0 :                 return -1;
    1663             : 
    1664         205 :         pos = buf;
    1665             :         /* WAN Info */
    1666         205 :         if (hexstr2bin(pos, wan_metrics, 1) < 0)
    1667           1 :                 goto fail;
    1668         204 :         pos += 2;
    1669         204 :         if (*pos != ':')
    1670           1 :                 goto fail;
    1671         203 :         pos++;
    1672             : 
    1673             :         /* Downlink Speed */
    1674         203 :         WPA_PUT_LE32(wan_metrics + 1, atoi(pos));
    1675         203 :         pos = os_strchr(pos, ':');
    1676         203 :         if (pos == NULL)
    1677           1 :                 goto fail;
    1678         202 :         pos++;
    1679             : 
    1680             :         /* Uplink Speed */
    1681         202 :         WPA_PUT_LE32(wan_metrics + 5, atoi(pos));
    1682         202 :         pos = os_strchr(pos, ':');
    1683         202 :         if (pos == NULL)
    1684           1 :                 goto fail;
    1685         201 :         pos++;
    1686             : 
    1687             :         /* Downlink Load */
    1688         201 :         wan_metrics[9] = atoi(pos);
    1689         201 :         pos = os_strchr(pos, ':');
    1690         201 :         if (pos == NULL)
    1691           1 :                 goto fail;
    1692         200 :         pos++;
    1693             : 
    1694             :         /* Uplink Load */
    1695         200 :         wan_metrics[10] = atoi(pos);
    1696         200 :         pos = os_strchr(pos, ':');
    1697         200 :         if (pos == NULL)
    1698           1 :                 goto fail;
    1699         199 :         pos++;
    1700             : 
    1701             :         /* LMD */
    1702         199 :         WPA_PUT_LE16(wan_metrics + 11, atoi(pos));
    1703             : 
    1704         199 :         os_free(bss->hs20_wan_metrics);
    1705         199 :         bss->hs20_wan_metrics = wan_metrics;
    1706             : 
    1707         199 :         return 0;
    1708             : 
    1709             : fail:
    1710           6 :         wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'",
    1711             :                    line, buf);
    1712           6 :         os_free(wan_metrics);
    1713           6 :         return -1;
    1714             : }
    1715             : 
    1716             : 
    1717          75 : static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
    1718             :                                          char *pos, int line)
    1719             : {
    1720          75 :         if (parse_lang_string(&bss->hs20_oper_friendly_name,
    1721             :                               &bss->hs20_oper_friendly_name_count, pos)) {
    1722           1 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
    1723             :                            "hs20_oper_friendly_name '%s'", line, pos);
    1724           1 :                 return -1;
    1725             :         }
    1726          74 :         return 0;
    1727             : }
    1728             : 
    1729             : 
    1730          19 : static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
    1731             : {
    1732             :         struct hs20_icon *icon;
    1733             :         char *end;
    1734             : 
    1735          19 :         icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
    1736             :                                 sizeof(struct hs20_icon));
    1737          19 :         if (icon == NULL)
    1738           0 :                 return -1;
    1739          19 :         bss->hs20_icons = icon;
    1740          19 :         icon = &bss->hs20_icons[bss->hs20_icons_count];
    1741          19 :         os_memset(icon, 0, sizeof(*icon));
    1742             : 
    1743          19 :         icon->width = atoi(pos);
    1744          19 :         pos = os_strchr(pos, ':');
    1745          19 :         if (pos == NULL)
    1746           1 :                 return -1;
    1747          18 :         pos++;
    1748             : 
    1749          18 :         icon->height = atoi(pos);
    1750          18 :         pos = os_strchr(pos, ':');
    1751          18 :         if (pos == NULL)
    1752           1 :                 return -1;
    1753          17 :         pos++;
    1754             : 
    1755          17 :         end = os_strchr(pos, ':');
    1756          17 :         if (end == NULL || end - pos > 3)
    1757           1 :                 return -1;
    1758          16 :         os_memcpy(icon->language, pos, end - pos);
    1759          16 :         pos = end + 1;
    1760             : 
    1761          16 :         end = os_strchr(pos, ':');
    1762          16 :         if (end == NULL || end - pos > 255)
    1763           1 :                 return -1;
    1764          15 :         os_memcpy(icon->type, pos, end - pos);
    1765          15 :         pos = end + 1;
    1766             : 
    1767          15 :         end = os_strchr(pos, ':');
    1768          15 :         if (end == NULL || end - pos > 255)
    1769           2 :                 return -1;
    1770          13 :         os_memcpy(icon->name, pos, end - pos);
    1771          13 :         pos = end + 1;
    1772             : 
    1773          13 :         if (os_strlen(pos) > 255)
    1774           1 :                 return -1;
    1775          12 :         os_memcpy(icon->file, pos, os_strlen(pos));
    1776             : 
    1777          12 :         bss->hs20_icons_count++;
    1778             : 
    1779          12 :         return 0;
    1780             : }
    1781             : 
    1782             : 
    1783          13 : static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
    1784             :                                char *pos, int line)
    1785             : {
    1786             :         size_t slen;
    1787             :         char *str;
    1788             : 
    1789          13 :         str = wpa_config_parse_string(pos, &slen);
    1790          13 :         if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
    1791           4 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
    1792           4 :                 os_free(str);
    1793           4 :                 return -1;
    1794             :         }
    1795             : 
    1796           9 :         os_memcpy(bss->osu_ssid, str, slen);
    1797           9 :         bss->osu_ssid_len = slen;
    1798           9 :         os_free(str);
    1799             : 
    1800           9 :         return 0;
    1801             : }
    1802             : 
    1803             : 
    1804          10 : static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
    1805             :                                      char *pos, int line)
    1806             : {
    1807             :         struct hs20_osu_provider *p;
    1808             : 
    1809          10 :         p = os_realloc_array(bss->hs20_osu_providers,
    1810          10 :                              bss->hs20_osu_providers_count + 1, sizeof(*p));
    1811          10 :         if (p == NULL)
    1812           0 :                 return -1;
    1813             : 
    1814          10 :         bss->hs20_osu_providers = p;
    1815          10 :         bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
    1816          10 :         bss->hs20_osu_providers_count++;
    1817          10 :         os_memset(bss->last_osu, 0, sizeof(*p));
    1818          10 :         bss->last_osu->server_uri = os_strdup(pos);
    1819             : 
    1820          10 :         return 0;
    1821             : }
    1822             : 
    1823             : 
    1824          21 : static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
    1825             :                                         char *pos, int line)
    1826             : {
    1827          21 :         if (bss->last_osu == NULL) {
    1828           1 :                 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
    1829           1 :                 return -1;
    1830             :         }
    1831             : 
    1832          20 :         if (parse_lang_string(&bss->last_osu->friendly_name,
    1833          20 :                               &bss->last_osu->friendly_name_count, pos)) {
    1834           1 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
    1835             :                            line, pos);
    1836           1 :                 return -1;
    1837             :         }
    1838             : 
    1839          19 :         return 0;
    1840             : }
    1841             : 
    1842             : 
    1843           2 : static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
    1844             :                               char *pos, int line)
    1845             : {
    1846           2 :         if (bss->last_osu == NULL) {
    1847           1 :                 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
    1848           1 :                 return -1;
    1849             :         }
    1850             : 
    1851           1 :         os_free(bss->last_osu->osu_nai);
    1852           1 :         bss->last_osu->osu_nai = os_strdup(pos);
    1853           1 :         if (bss->last_osu->osu_nai == NULL)
    1854           0 :                 return -1;
    1855             : 
    1856           1 :         return 0;
    1857             : }
    1858             : 
    1859             : 
    1860          10 : static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
    1861             :                                       int line)
    1862             : {
    1863          10 :         if (bss->last_osu == NULL) {
    1864           1 :                 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
    1865           1 :                 return -1;
    1866             :         }
    1867             : 
    1868           9 :         if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
    1869           0 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
    1870           0 :                 return -1;
    1871             :         }
    1872             : 
    1873           9 :         return 0;
    1874             : }
    1875             : 
    1876             : 
    1877          13 : static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
    1878             :                                int line)
    1879             : {
    1880             :         char **n;
    1881          13 :         struct hs20_osu_provider *p = bss->last_osu;
    1882             : 
    1883          13 :         if (p == NULL) {
    1884           1 :                 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
    1885           1 :                 return -1;
    1886             :         }
    1887             : 
    1888          12 :         n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
    1889          12 :         if (n == NULL)
    1890           0 :                 return -1;
    1891          12 :         p->icons = n;
    1892          12 :         p->icons[p->icons_count] = os_strdup(pos);
    1893          12 :         if (p->icons[p->icons_count] == NULL)
    1894           0 :                 return -1;
    1895          12 :         p->icons_count++;
    1896             : 
    1897          12 :         return 0;
    1898             : }
    1899             : 
    1900             : 
    1901          20 : static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
    1902             :                                        char *pos, int line)
    1903             : {
    1904          20 :         if (bss->last_osu == NULL) {
    1905           1 :                 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
    1906           1 :                 return -1;
    1907             :         }
    1908             : 
    1909          19 :         if (parse_lang_string(&bss->last_osu->service_desc,
    1910          19 :                               &bss->last_osu->service_desc_count, pos)) {
    1911           1 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
    1912             :                            line, pos);
    1913           1 :                 return -1;
    1914             :         }
    1915             : 
    1916          18 :         return 0;
    1917             : }
    1918             : 
    1919             : #endif /* CONFIG_HS20 */
    1920             : 
    1921             : 
    1922             : #ifdef CONFIG_ACS
    1923           1 : static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
    1924             :                                               char *pos)
    1925             : {
    1926           1 :         struct acs_bias *bias = NULL, *tmp;
    1927           1 :         unsigned int num = 0;
    1928             :         char *end;
    1929             : 
    1930           6 :         while (*pos) {
    1931           4 :                 tmp = os_realloc_array(bias, num + 1, sizeof(*bias));
    1932           4 :                 if (!tmp)
    1933           0 :                         goto fail;
    1934           4 :                 bias = tmp;
    1935             : 
    1936           4 :                 bias[num].channel = atoi(pos);
    1937           4 :                 if (bias[num].channel <= 0)
    1938           0 :                         goto fail;
    1939           4 :                 pos = os_strchr(pos, ':');
    1940           4 :                 if (!pos)
    1941           0 :                         goto fail;
    1942           4 :                 pos++;
    1943           4 :                 bias[num].bias = strtod(pos, &end);
    1944           4 :                 if (end == pos || bias[num].bias < 0.0)
    1945             :                         goto fail;
    1946           4 :                 pos = end;
    1947           4 :                 if (*pos != ' ' && *pos != '\0')
    1948           0 :                         goto fail;
    1949           4 :                 num++;
    1950             :         }
    1951             : 
    1952           1 :         os_free(conf->acs_chan_bias);
    1953           1 :         conf->acs_chan_bias = bias;
    1954           1 :         conf->num_acs_chan_bias = num;
    1955             : 
    1956           1 :         return 0;
    1957             : fail:
    1958           0 :         os_free(bias);
    1959           0 :         return -1;
    1960             : }
    1961             : #endif /* CONFIG_ACS */
    1962             : 
    1963             : 
    1964          19 : static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf,
    1965             :                             const char *val)
    1966             : {
    1967             :         struct wpabuf *elems;
    1968             : 
    1969          19 :         if (val[0] == '\0') {
    1970           0 :                 wpabuf_free(*buf);
    1971           0 :                 *buf = NULL;
    1972           0 :                 return 0;
    1973             :         }
    1974             : 
    1975          19 :         elems = wpabuf_parse_bin(val);
    1976          19 :         if (!elems) {
    1977           4 :                 wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
    1978             :                            line, name, val);
    1979           4 :                 return -1;
    1980             :         }
    1981             : 
    1982          15 :         wpabuf_free(*buf);
    1983          15 :         *buf = elems;
    1984             : 
    1985          15 :         return 0;
    1986             : }
    1987             : 
    1988             : 
    1989       31952 : static int hostapd_config_fill(struct hostapd_config *conf,
    1990             :                                struct hostapd_bss_config *bss,
    1991             :                                const char *buf, char *pos, int line)
    1992             : {
    1993       31952 :         if (os_strcmp(buf, "interface") == 0) {
    1994          95 :                 os_strlcpy(conf->bss[0]->iface, pos,
    1995             :                            sizeof(conf->bss[0]->iface));
    1996       31857 :         } else if (os_strcmp(buf, "bridge") == 0) {
    1997          34 :                 os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
    1998       31823 :         } else if (os_strcmp(buf, "vlan_bridge") == 0) {
    1999           4 :                 os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
    2000       31819 :         } else if (os_strcmp(buf, "wds_bridge") == 0) {
    2001           1 :                 os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
    2002       31818 :         } else if (os_strcmp(buf, "driver") == 0) {
    2003             :                 int j;
    2004             :                 /* clear to get error below if setting is invalid */
    2005        2060 :                 conf->driver = NULL;
    2006        2072 :                 for (j = 0; wpa_drivers[j]; j++) {
    2007        2072 :                         if (os_strcmp(pos, wpa_drivers[j]->name) == 0) {
    2008        2060 :                                 conf->driver = wpa_drivers[j];
    2009        2060 :                                 break;
    2010             :                         }
    2011             :                 }
    2012        2060 :                 if (conf->driver == NULL) {
    2013           0 :                         wpa_printf(MSG_ERROR,
    2014             :                                    "Line %d: invalid/unknown driver '%s'",
    2015             :                                    line, pos);
    2016           0 :                         return 1;
    2017             :                 }
    2018       29758 :         } else if (os_strcmp(buf, "driver_params") == 0) {
    2019           2 :                 os_free(conf->driver_params);
    2020           2 :                 conf->driver_params = os_strdup(pos);
    2021       29756 :         } else if (os_strcmp(buf, "debug") == 0) {
    2022           0 :                 wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore",
    2023             :                            line);
    2024       29756 :         } else if (os_strcmp(buf, "logger_syslog_level") == 0) {
    2025           0 :                 bss->logger_syslog_level = atoi(pos);
    2026       29756 :         } else if (os_strcmp(buf, "logger_stdout_level") == 0) {
    2027        1975 :                 bss->logger_stdout_level = atoi(pos);
    2028       27781 :         } else if (os_strcmp(buf, "logger_syslog") == 0) {
    2029           0 :                 bss->logger_syslog = atoi(pos);
    2030       27781 :         } else if (os_strcmp(buf, "logger_stdout") == 0) {
    2031        1978 :                 bss->logger_stdout = atoi(pos);
    2032       25803 :         } else if (os_strcmp(buf, "dump_file") == 0) {
    2033           0 :                 wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
    2034             :                            line);
    2035       25803 :         } else if (os_strcmp(buf, "ssid") == 0) {
    2036        2066 :                 bss->ssid.ssid_len = os_strlen(pos);
    2037        4131 :                 if (bss->ssid.ssid_len > SSID_MAX_LEN ||
    2038        2065 :                     bss->ssid.ssid_len < 1) {
    2039           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
    2040             :                                    line, pos);
    2041           1 :                         return 1;
    2042             :                 }
    2043        2065 :                 os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len);
    2044        2065 :                 bss->ssid.ssid_set = 1;
    2045       23737 :         } else if (os_strcmp(buf, "ssid2") == 0) {
    2046             :                 size_t slen;
    2047           3 :                 char *str = wpa_config_parse_string(pos, &slen);
    2048           3 :                 if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
    2049           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
    2050             :                                    line, pos);
    2051           0 :                         os_free(str);
    2052           0 :                         return 1;
    2053             :                 }
    2054           3 :                 os_memcpy(bss->ssid.ssid, str, slen);
    2055           3 :                 bss->ssid.ssid_len = slen;
    2056           3 :                 bss->ssid.ssid_set = 1;
    2057           3 :                 os_free(str);
    2058       23734 :         } else if (os_strcmp(buf, "utf8_ssid") == 0) {
    2059           1 :                 bss->ssid.utf8_ssid = atoi(pos) > 0;
    2060       23733 :         } else if (os_strcmp(buf, "macaddr_acl") == 0) {
    2061           8 :                 bss->macaddr_acl = atoi(pos);
    2062          16 :                 if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
    2063          14 :                     bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
    2064           6 :                     bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
    2065           0 :                         wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d",
    2066           0 :                                    line, bss->macaddr_acl);
    2067             :                 }
    2068       23725 :         } else if (os_strcmp(buf, "accept_mac_file") == 0) {
    2069           8 :                 if (hostapd_config_read_maclist(pos, &bss->accept_mac,
    2070             :                                                 &bss->num_accept_mac)) {
    2071           0 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'",
    2072             :                                    line, pos);
    2073           0 :                         return 1;
    2074             :                 }
    2075       23717 :         } else if (os_strcmp(buf, "deny_mac_file") == 0) {
    2076           2 :                 if (hostapd_config_read_maclist(pos, &bss->deny_mac,
    2077             :                                                 &bss->num_deny_mac)) {
    2078           0 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'",
    2079             :                                    line, pos);
    2080           0 :                         return 1;
    2081             :                 }
    2082       23715 :         } else if (os_strcmp(buf, "wds_sta") == 0) {
    2083           1 :                 bss->wds_sta = atoi(pos);
    2084       23714 :         } else if (os_strcmp(buf, "start_disabled") == 0) {
    2085           2 :                 bss->start_disabled = atoi(pos);
    2086       23712 :         } else if (os_strcmp(buf, "ap_isolate") == 0) {
    2087          12 :                 bss->isolate = atoi(pos);
    2088       23700 :         } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
    2089           4 :                 bss->ap_max_inactivity = atoi(pos);
    2090       23696 :         } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
    2091           1 :                 bss->skip_inactivity_poll = atoi(pos);
    2092       23695 :         } else if (os_strcmp(buf, "country_code") == 0) {
    2093         395 :                 os_memcpy(conf->country, pos, 2);
    2094             :                 /* FIX: make this configurable */
    2095         395 :                 conf->country[2] = ' ';
    2096       23300 :         } else if (os_strcmp(buf, "ieee80211d") == 0) {
    2097          43 :                 conf->ieee80211d = atoi(pos);
    2098       23257 :         } else if (os_strcmp(buf, "ieee80211h") == 0) {
    2099          17 :                 conf->ieee80211h = atoi(pos);
    2100       23240 :         } else if (os_strcmp(buf, "ieee8021x") == 0) {
    2101         672 :                 bss->ieee802_1x = atoi(pos);
    2102       22568 :         } else if (os_strcmp(buf, "eapol_version") == 0) {
    2103           0 :                 bss->eapol_version = atoi(pos);
    2104           0 :                 if (bss->eapol_version < 1 || bss->eapol_version > 2) {
    2105           0 :                         wpa_printf(MSG_ERROR,
    2106             :                                    "Line %d: invalid EAPOL version (%d): '%s'.",
    2107             :                                    line, bss->eapol_version, pos);
    2108           0 :                         return 1;
    2109             :                 }
    2110           0 :                 wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version);
    2111             : #ifdef EAP_SERVER
    2112       22568 :         } else if (os_strcmp(buf, "eap_authenticator") == 0) {
    2113           0 :                 bss->eap_server = atoi(pos);
    2114           0 :                 wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line);
    2115       22568 :         } else if (os_strcmp(buf, "eap_server") == 0) {
    2116         398 :                 bss->eap_server = atoi(pos);
    2117       22170 :         } else if (os_strcmp(buf, "eap_user_file") == 0) {
    2118         143 :                 if (hostapd_config_read_eap_user(pos, bss))
    2119           0 :                         return 1;
    2120       22027 :         } else if (os_strcmp(buf, "ca_cert") == 0) {
    2121         123 :                 os_free(bss->ca_cert);
    2122         123 :                 bss->ca_cert = os_strdup(pos);
    2123       21904 :         } else if (os_strcmp(buf, "server_cert") == 0) {
    2124         120 :                 os_free(bss->server_cert);
    2125         120 :                 bss->server_cert = os_strdup(pos);
    2126       21784 :         } else if (os_strcmp(buf, "private_key") == 0) {
    2127         122 :                 os_free(bss->private_key);
    2128         122 :                 bss->private_key = os_strdup(pos);
    2129       21662 :         } else if (os_strcmp(buf, "private_key_passwd") == 0) {
    2130           1 :                 os_free(bss->private_key_passwd);
    2131           1 :                 bss->private_key_passwd = os_strdup(pos);
    2132       21661 :         } else if (os_strcmp(buf, "check_crl") == 0) {
    2133           2 :                 bss->check_crl = atoi(pos);
    2134       21659 :         } else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
    2135          12 :                 bss->tls_session_lifetime = atoi(pos);
    2136       21647 :         } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
    2137          25 :                 os_free(bss->ocsp_stapling_response);
    2138          25 :                 bss->ocsp_stapling_response = os_strdup(pos);
    2139       21622 :         } else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) {
    2140          12 :                 os_free(bss->ocsp_stapling_response_multi);
    2141          12 :                 bss->ocsp_stapling_response_multi = os_strdup(pos);
    2142       21610 :         } else if (os_strcmp(buf, "dh_file") == 0) {
    2143         104 :                 os_free(bss->dh_file);
    2144         104 :                 bss->dh_file = os_strdup(pos);
    2145       21506 :         } else if (os_strcmp(buf, "openssl_ciphers") == 0) {
    2146          10 :                 os_free(bss->openssl_ciphers);
    2147          10 :                 bss->openssl_ciphers = os_strdup(pos);
    2148       21496 :         } else if (os_strcmp(buf, "fragment_size") == 0) {
    2149           9 :                 bss->fragment_size = atoi(pos);
    2150             : #ifdef EAP_SERVER_FAST
    2151       21487 :         } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
    2152          30 :                 os_free(bss->pac_opaque_encr_key);
    2153          30 :                 bss->pac_opaque_encr_key = os_malloc(16);
    2154          30 :                 if (bss->pac_opaque_encr_key == NULL) {
    2155           0 :                         wpa_printf(MSG_ERROR,
    2156             :                                    "Line %d: No memory for pac_opaque_encr_key",
    2157             :                                    line);
    2158           0 :                         return 1;
    2159          30 :                 } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) {
    2160           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key",
    2161             :                                    line);
    2162           1 :                         return 1;
    2163             :                 }
    2164       21457 :         } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
    2165          31 :                 size_t idlen = os_strlen(pos);
    2166          31 :                 if (idlen & 1) {
    2167           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id",
    2168             :                                    line);
    2169           1 :                         return 1;
    2170             :                 }
    2171          30 :                 os_free(bss->eap_fast_a_id);
    2172          30 :                 bss->eap_fast_a_id = os_malloc(idlen / 2);
    2173          60 :                 if (bss->eap_fast_a_id == NULL ||
    2174          30 :                     hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) {
    2175           1 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id",
    2176             :                                    line);
    2177           1 :                         os_free(bss->eap_fast_a_id);
    2178           1 :                         bss->eap_fast_a_id = NULL;
    2179           1 :                         return 1;
    2180             :                 } else {
    2181          29 :                         bss->eap_fast_a_id_len = idlen / 2;
    2182             :                 }
    2183       21426 :         } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
    2184          29 :                 os_free(bss->eap_fast_a_id_info);
    2185          29 :                 bss->eap_fast_a_id_info = os_strdup(pos);
    2186       21397 :         } else if (os_strcmp(buf, "eap_fast_prov") == 0) {
    2187           0 :                 bss->eap_fast_prov = atoi(pos);
    2188       21397 :         } else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
    2189           5 :                 bss->pac_key_lifetime = atoi(pos);
    2190       21392 :         } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
    2191           5 :                 bss->pac_key_refresh_time = atoi(pos);
    2192             : #endif /* EAP_SERVER_FAST */
    2193             : #ifdef EAP_SERVER_SIM
    2194       21387 :         } else if (os_strcmp(buf, "eap_sim_db") == 0) {
    2195          18 :                 os_free(bss->eap_sim_db);
    2196          18 :                 bss->eap_sim_db = os_strdup(pos);
    2197       21369 :         } else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) {
    2198           0 :                 bss->eap_sim_db_timeout = atoi(pos);
    2199       21369 :         } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
    2200          15 :                 bss->eap_sim_aka_result_ind = atoi(pos);
    2201             : #endif /* EAP_SERVER_SIM */
    2202             : #ifdef EAP_SERVER_TNC
    2203       21354 :         } else if (os_strcmp(buf, "tnc") == 0) {
    2204           6 :                 bss->tnc = atoi(pos);
    2205             : #endif /* EAP_SERVER_TNC */
    2206             : #ifdef EAP_SERVER_PWD
    2207       21348 :         } else if (os_strcmp(buf, "pwd_group") == 0) {
    2208          12 :                 bss->pwd_group = atoi(pos);
    2209             : #endif /* EAP_SERVER_PWD */
    2210       21336 :         } else if (os_strcmp(buf, "eap_server_erp") == 0) {
    2211           9 :                 bss->eap_server_erp = atoi(pos);
    2212             : #endif /* EAP_SERVER */
    2213       21327 :         } else if (os_strcmp(buf, "eap_message") == 0) {
    2214             :                 char *term;
    2215           1 :                 os_free(bss->eap_req_id_text);
    2216           1 :                 bss->eap_req_id_text = os_strdup(pos);
    2217           1 :                 if (bss->eap_req_id_text == NULL) {
    2218           0 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text",
    2219             :                                    line);
    2220           0 :                         return 1;
    2221             :                 }
    2222           1 :                 bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text);
    2223           1 :                 term = os_strstr(bss->eap_req_id_text, "\\0");
    2224           1 :                 if (term) {
    2225           1 :                         *term++ = '\0';
    2226           1 :                         os_memmove(term, term + 1,
    2227             :                                    bss->eap_req_id_text_len -
    2228             :                                    (term - bss->eap_req_id_text) - 1);
    2229           1 :                         bss->eap_req_id_text_len--;
    2230             :                 }
    2231       21326 :         } else if (os_strcmp(buf, "erp_send_reauth_start") == 0) {
    2232          10 :                 bss->erp_send_reauth_start = atoi(pos);
    2233       21316 :         } else if (os_strcmp(buf, "erp_domain") == 0) {
    2234          12 :                 os_free(bss->erp_domain);
    2235          12 :                 bss->erp_domain = os_strdup(pos);
    2236       21304 :         } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
    2237           7 :                 bss->default_wep_key_len = atoi(pos);
    2238           7 :                 if (bss->default_wep_key_len > 13) {
    2239           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WEP key len %lu (= %lu bits)",
    2240             :                                    line,
    2241             :                                    (unsigned long) bss->default_wep_key_len,
    2242             :                                    (unsigned long)
    2243           1 :                                    bss->default_wep_key_len * 8);
    2244           1 :                         return 1;
    2245             :                 }
    2246       21297 :         } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
    2247           6 :                 bss->individual_wep_key_len = atoi(pos);
    2248          12 :                 if (bss->individual_wep_key_len < 0 ||
    2249           6 :                     bss->individual_wep_key_len > 13) {
    2250           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WEP key len %d (= %d bits)",
    2251             :                                    line, bss->individual_wep_key_len,
    2252           0 :                                    bss->individual_wep_key_len * 8);
    2253           0 :                         return 1;
    2254             :                 }
    2255       21291 :         } else if (os_strcmp(buf, "wep_rekey_period") == 0) {
    2256           1 :                 bss->wep_rekeying_period = atoi(pos);
    2257           1 :                 if (bss->wep_rekeying_period < 0) {
    2258           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
    2259             :                                    line, bss->wep_rekeying_period);
    2260           1 :                         return 1;
    2261             :                 }
    2262       21290 :         } else if (os_strcmp(buf, "eap_reauth_period") == 0) {
    2263           1 :                 bss->eap_reauth_period = atoi(pos);
    2264           1 :                 if (bss->eap_reauth_period < 0) {
    2265           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
    2266             :                                    line, bss->eap_reauth_period);
    2267           0 :                         return 1;
    2268             :                 }
    2269       21289 :         } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
    2270           0 :                 bss->eapol_key_index_workaround = atoi(pos);
    2271             : #ifdef CONFIG_IAPP
    2272       21289 :         } else if (os_strcmp(buf, "iapp_interface") == 0) {
    2273           2 :                 bss->ieee802_11f = 1;
    2274           2 :                 os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
    2275             : #endif /* CONFIG_IAPP */
    2276       21287 :         } else if (os_strcmp(buf, "own_ip_addr") == 0) {
    2277           3 :                 if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
    2278           1 :                         wpa_printf(MSG_ERROR,
    2279             :                                    "Line %d: invalid IP address '%s'",
    2280             :                                    line, pos);
    2281           1 :                         return 1;
    2282             :                 }
    2283       21284 :         } else if (os_strcmp(buf, "nas_identifier") == 0) {
    2284         431 :                 os_free(bss->nas_identifier);
    2285         431 :                 bss->nas_identifier = os_strdup(pos);
    2286             : #ifndef CONFIG_NO_RADIUS
    2287       20853 :         } else if (os_strcmp(buf, "radius_client_addr") == 0) {
    2288           2 :                 if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) {
    2289           0 :                         wpa_printf(MSG_ERROR,
    2290             :                                    "Line %d: invalid IP address '%s'",
    2291             :                                    line, pos);
    2292           0 :                         return 1;
    2293             :                 }
    2294           2 :                 bss->radius->force_client_addr = 1;
    2295       20851 :         } else if (os_strcmp(buf, "auth_server_addr") == 0) {
    2296        1719 :                 if (hostapd_config_read_radius_addr(
    2297         573 :                             &bss->radius->auth_servers,
    2298         573 :                             &bss->radius->num_auth_servers, pos, 1812,
    2299         573 :                             &bss->radius->auth_server)) {
    2300           2 :                         wpa_printf(MSG_ERROR,
    2301             :                                    "Line %d: invalid IP address '%s'",
    2302             :                                    line, pos);
    2303           2 :                         return 1;
    2304             :                 }
    2305       27161 :         } else if (bss->radius->auth_server &&
    2306        6883 :                    os_strcmp(buf, "auth_server_addr_replace") == 0) {
    2307           2 :                 if (hostapd_parse_ip_addr(pos,
    2308           1 :                                           &bss->radius->auth_server->addr)) {
    2309           0 :                         wpa_printf(MSG_ERROR,
    2310             :                                    "Line %d: invalid IP address '%s'",
    2311             :                                    line, pos);
    2312           0 :                         return 1;
    2313             :                 }
    2314       27159 :         } else if (bss->radius->auth_server &&
    2315        6882 :                    os_strcmp(buf, "auth_server_port") == 0) {
    2316         568 :                 bss->radius->auth_server->port = atoi(pos);
    2317       26023 :         } else if (bss->radius->auth_server &&
    2318        6884 :                    os_strcmp(buf, "auth_server_shared_secret") == 0) {
    2319         571 :                 int len = os_strlen(pos);
    2320         571 :                 if (len == 0) {
    2321             :                         /* RFC 2865, Ch. 3 */
    2322           1 :                         wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
    2323             :                                    line);
    2324           1 :                         return 1;
    2325             :                 }
    2326         570 :                 os_free(bss->radius->auth_server->shared_secret);
    2327         570 :                 bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
    2328         570 :                 bss->radius->auth_server->shared_secret_len = len;
    2329       19138 :         } else if (os_strcmp(buf, "acct_server_addr") == 0) {
    2330         222 :                 if (hostapd_config_read_radius_addr(
    2331          74 :                             &bss->radius->acct_servers,
    2332          74 :                             &bss->radius->num_acct_servers, pos, 1813,
    2333          74 :                             &bss->radius->acct_server)) {
    2334           2 :                         wpa_printf(MSG_ERROR,
    2335             :                                    "Line %d: invalid IP address '%s'",
    2336             :                                    line, pos);
    2337           2 :                         return 1;
    2338             :                 }
    2339       19320 :         } else if (bss->radius->acct_server &&
    2340         256 :                    os_strcmp(buf, "acct_server_addr_replace") == 0) {
    2341           2 :                 if (hostapd_parse_ip_addr(pos,
    2342           1 :                                           &bss->radius->acct_server->addr)) {
    2343           0 :                         wpa_printf(MSG_ERROR,
    2344             :                                    "Line %d: invalid IP address '%s'",
    2345             :                                    line, pos);
    2346           0 :                         return 1;
    2347             :                 }
    2348       19318 :         } else if (bss->radius->acct_server &&
    2349         255 :                    os_strcmp(buf, "acct_server_port") == 0) {
    2350          68 :                 bss->radius->acct_server->port = atoi(pos);
    2351       19182 :         } else if (bss->radius->acct_server &&
    2352         258 :                    os_strcmp(buf, "acct_server_shared_secret") == 0) {
    2353          72 :                 int len = os_strlen(pos);
    2354          72 :                 if (len == 0) {
    2355             :                         /* RFC 2865, Ch. 3 */
    2356           1 :                         wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
    2357             :                                    line);
    2358           1 :                         return 1;
    2359             :                 }
    2360          71 :                 os_free(bss->radius->acct_server->shared_secret);
    2361          71 :                 bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
    2362          71 :                 bss->radius->acct_server->shared_secret_len = len;
    2363       18923 :         } else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
    2364           1 :                 bss->radius->retry_primary_interval = atoi(pos);
    2365       18922 :         } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
    2366           3 :                 bss->acct_interim_interval = atoi(pos);
    2367       18919 :         } else if (os_strcmp(buf, "radius_request_cui") == 0) {
    2368           1 :                 bss->radius_request_cui = atoi(pos);
    2369       18918 :         } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
    2370             :                 struct hostapd_radius_attr *attr, *a;
    2371           3 :                 attr = hostapd_parse_radius_attr(pos);
    2372           3 :                 if (attr == NULL) {
    2373           1 :                         wpa_printf(MSG_ERROR,
    2374             :                                    "Line %d: invalid radius_auth_req_attr",
    2375             :                                    line);
    2376           1 :                         return 1;
    2377           2 :                 } else if (bss->radius_auth_req_attr == NULL) {
    2378           1 :                         bss->radius_auth_req_attr = attr;
    2379             :                 } else {
    2380           1 :                         a = bss->radius_auth_req_attr;
    2381           2 :                         while (a->next)
    2382           0 :                                 a = a->next;
    2383           1 :                         a->next = attr;
    2384             :                 }
    2385       18915 :         } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
    2386             :                 struct hostapd_radius_attr *attr, *a;
    2387           3 :                 attr = hostapd_parse_radius_attr(pos);
    2388           3 :                 if (attr == NULL) {
    2389           1 :                         wpa_printf(MSG_ERROR,
    2390             :                                    "Line %d: invalid radius_acct_req_attr",
    2391             :                                    line);
    2392           1 :                         return 1;
    2393           2 :                 } else if (bss->radius_acct_req_attr == NULL) {
    2394           1 :                         bss->radius_acct_req_attr = attr;
    2395             :                 } else {
    2396           1 :                         a = bss->radius_acct_req_attr;
    2397           2 :                         while (a->next)
    2398           0 :                                 a = a->next;
    2399           1 :                         a->next = attr;
    2400             :                 }
    2401       18912 :         } else if (os_strcmp(buf, "radius_das_port") == 0) {
    2402           2 :                 bss->radius_das_port = atoi(pos);
    2403       18910 :         } else if (os_strcmp(buf, "radius_das_client") == 0) {
    2404           4 :                 if (hostapd_parse_das_client(bss, pos) < 0) {
    2405           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid DAS client",
    2406             :                                    line);
    2407           2 :                         return 1;
    2408             :                 }
    2409       18906 :         } else if (os_strcmp(buf, "radius_das_time_window") == 0) {
    2410           0 :                 bss->radius_das_time_window = atoi(pos);
    2411       18906 :         } else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
    2412           2 :                 bss->radius_das_require_event_timestamp = atoi(pos);
    2413       18904 :         } else if (os_strcmp(buf, "radius_das_require_message_authenticator") ==
    2414             :                    0) {
    2415           0 :                 bss->radius_das_require_message_authenticator = atoi(pos);
    2416             : #endif /* CONFIG_NO_RADIUS */
    2417       18904 :         } else if (os_strcmp(buf, "auth_algs") == 0) {
    2418           9 :                 bss->auth_algs = atoi(pos);
    2419           9 :                 if (bss->auth_algs == 0) {
    2420           1 :                         wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed",
    2421             :                                    line);
    2422           1 :                         return 1;
    2423             :                 }
    2424       18895 :         } else if (os_strcmp(buf, "max_num_sta") == 0) {
    2425           5 :                 bss->max_num_sta = atoi(pos);
    2426           9 :                 if (bss->max_num_sta < 0 ||
    2427           4 :                     bss->max_num_sta > MAX_STA_COUNT) {
    2428           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
    2429             :                                    line, bss->max_num_sta, MAX_STA_COUNT);
    2430           2 :                         return 1;
    2431             :                 }
    2432       18890 :         } else if (os_strcmp(buf, "wpa") == 0) {
    2433        1172 :                 bss->wpa = atoi(pos);
    2434       17718 :         } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
    2435           5 :                 bss->wpa_group_rekey = atoi(pos);
    2436       17713 :         } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
    2437           1 :                 bss->wpa_strict_rekey = atoi(pos);
    2438       17712 :         } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
    2439           1 :                 bss->wpa_gmk_rekey = atoi(pos);
    2440       17711 :         } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
    2441           6 :                 bss->wpa_ptk_rekey = atoi(pos);
    2442       17705 :         } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
    2443         501 :                 int len = os_strlen(pos);
    2444         501 :                 if (len < 8 || len > 63) {
    2445           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)",
    2446             :                                    line, len);
    2447           2 :                         return 1;
    2448             :                 }
    2449         499 :                 os_free(bss->ssid.wpa_passphrase);
    2450         499 :                 bss->ssid.wpa_passphrase = os_strdup(pos);
    2451         499 :                 if (bss->ssid.wpa_passphrase) {
    2452         498 :                         hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
    2453         498 :                         bss->ssid.wpa_passphrase_set = 1;
    2454             :                 }
    2455       17204 :         } else if (os_strcmp(buf, "wpa_psk") == 0) {
    2456          36 :                 hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
    2457          36 :                 bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
    2458          36 :                 if (bss->ssid.wpa_psk == NULL)
    2459           0 :                         return 1;
    2460          71 :                 if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) ||
    2461          35 :                     pos[PMK_LEN * 2] != '\0') {
    2462           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
    2463             :                                    line, pos);
    2464           2 :                         hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
    2465           2 :                         return 1;
    2466             :                 }
    2467          34 :                 bss->ssid.wpa_psk->group = 1;
    2468          34 :                 os_free(bss->ssid.wpa_passphrase);
    2469          34 :                 bss->ssid.wpa_passphrase = NULL;
    2470          34 :                 bss->ssid.wpa_psk_set = 1;
    2471       17168 :         } else if (os_strcmp(buf, "wpa_psk_file") == 0) {
    2472          25 :                 os_free(bss->ssid.wpa_psk_file);
    2473          25 :                 bss->ssid.wpa_psk_file = os_strdup(pos);
    2474          25 :                 if (!bss->ssid.wpa_psk_file) {
    2475           1 :                         wpa_printf(MSG_ERROR, "Line %d: allocation failed",
    2476             :                                    line);
    2477           1 :                         return 1;
    2478             :                 }
    2479       17143 :         } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
    2480        1181 :                 bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
    2481        1181 :                 if (bss->wpa_key_mgmt == -1)
    2482           5 :                         return 1;
    2483       15962 :         } else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
    2484           4 :                 bss->wpa_psk_radius = atoi(pos);
    2485           8 :                 if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
    2486           7 :                     bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
    2487           3 :                     bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
    2488           1 :                         wpa_printf(MSG_ERROR,
    2489             :                                    "Line %d: unknown wpa_psk_radius %d",
    2490           1 :                                    line, bss->wpa_psk_radius);
    2491           1 :                         return 1;
    2492             :                 }
    2493       15958 :         } else if (os_strcmp(buf, "wpa_pairwise") == 0) {
    2494          30 :                 bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos);
    2495          30 :                 if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0)
    2496           2 :                         return 1;
    2497          28 :                 if (bss->wpa_pairwise &
    2498             :                     (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
    2499           3 :                         wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
    2500             :                                    bss->wpa_pairwise, pos);
    2501           3 :                         return 1;
    2502             :                 }
    2503       15928 :         } else if (os_strcmp(buf, "rsn_pairwise") == 0) {
    2504        1158 :                 bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos);
    2505        1158 :                 if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0)
    2506           2 :                         return 1;
    2507        1156 :                 if (bss->rsn_pairwise &
    2508             :                     (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
    2509           3 :                         wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
    2510             :                                    bss->rsn_pairwise, pos);
    2511           3 :                         return 1;
    2512             :                 }
    2513             : #ifdef CONFIG_RSN_PREAUTH
    2514       14770 :         } else if (os_strcmp(buf, "rsn_preauth") == 0) {
    2515           7 :                 bss->rsn_preauth = atoi(pos);
    2516       14763 :         } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
    2517           7 :                 os_free(bss->rsn_preauth_interfaces);
    2518           7 :                 bss->rsn_preauth_interfaces = os_strdup(pos);
    2519             : #endif /* CONFIG_RSN_PREAUTH */
    2520             : #ifdef CONFIG_PEERKEY
    2521       14756 :         } else if (os_strcmp(buf, "peerkey") == 0) {
    2522           3 :                 bss->peerkey = atoi(pos);
    2523             : #endif /* CONFIG_PEERKEY */
    2524             : #ifdef CONFIG_IEEE80211R
    2525       14753 :         } else if (os_strcmp(buf, "mobility_domain") == 0) {
    2526         117 :                 if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
    2527          58 :                     hexstr2bin(pos, bss->mobility_domain,
    2528             :                                MOBILITY_DOMAIN_ID_LEN) != 0) {
    2529           1 :                         wpa_printf(MSG_ERROR,
    2530             :                                    "Line %d: Invalid mobility_domain '%s'",
    2531             :                                    line, pos);
    2532           1 :                         return 1;
    2533             :                 }
    2534       14694 :         } else if (os_strcmp(buf, "r1_key_holder") == 0) {
    2535         117 :                 if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
    2536          58 :                     hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) {
    2537           1 :                         wpa_printf(MSG_ERROR,
    2538             :                                    "Line %d: Invalid r1_key_holder '%s'",
    2539             :                                    line, pos);
    2540           1 :                         return 1;
    2541             :                 }
    2542       14635 :         } else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
    2543          57 :                 bss->r0_key_lifetime = atoi(pos);
    2544       14578 :         } else if (os_strcmp(buf, "reassociation_deadline") == 0) {
    2545          58 :                 bss->reassociation_deadline = atoi(pos);
    2546       14520 :         } else if (os_strcmp(buf, "r0kh") == 0) {
    2547         117 :                 if (add_r0kh(bss, pos) < 0) {
    2548           3 :                         wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'",
    2549             :                                    line, pos);
    2550           3 :                         return 1;
    2551             :                 }
    2552       14403 :         } else if (os_strcmp(buf, "r1kh") == 0) {
    2553          60 :                 if (add_r1kh(bss, pos) < 0) {
    2554           3 :                         wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'",
    2555             :                                    line, pos);
    2556           3 :                         return 1;
    2557             :                 }
    2558       14343 :         } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
    2559          57 :                 bss->pmk_r1_push = atoi(pos);
    2560       14286 :         } else if (os_strcmp(buf, "ft_over_ds") == 0) {
    2561           0 :                 bss->ft_over_ds = atoi(pos);
    2562             : #endif /* CONFIG_IEEE80211R */
    2563             : #ifndef CONFIG_NO_CTRL_IFACE
    2564       14286 :         } else if (os_strcmp(buf, "ctrl_interface") == 0) {
    2565         103 :                 os_free(bss->ctrl_interface);
    2566         103 :                 bss->ctrl_interface = os_strdup(pos);
    2567       14183 :         } else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
    2568             : #ifndef CONFIG_NATIVE_WINDOWS
    2569             :                 struct group *grp;
    2570             :                 char *endp;
    2571          13 :                 const char *group = pos;
    2572             : 
    2573          13 :                 grp = getgrnam(group);
    2574          13 :                 if (grp) {
    2575          12 :                         bss->ctrl_interface_gid = grp->gr_gid;
    2576          12 :                         bss->ctrl_interface_gid_set = 1;
    2577          12 :                         wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')",
    2578             :                                    bss->ctrl_interface_gid, group);
    2579          25 :                         return 0;
    2580             :                 }
    2581             : 
    2582             :                 /* Group name not found - try to parse this as gid */
    2583           1 :                 bss->ctrl_interface_gid = strtol(group, &endp, 10);
    2584           1 :                 if (*group == '\0' || *endp != '\0') {
    2585           1 :                         wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'",
    2586             :                                    line, group);
    2587           1 :                         return 1;
    2588             :                 }
    2589           0 :                 bss->ctrl_interface_gid_set = 1;
    2590           0 :                 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
    2591             :                            bss->ctrl_interface_gid);
    2592             : #endif /* CONFIG_NATIVE_WINDOWS */
    2593             : #endif /* CONFIG_NO_CTRL_IFACE */
    2594             : #ifdef RADIUS_SERVER
    2595       14170 :         } else if (os_strcmp(buf, "radius_server_clients") == 0) {
    2596          26 :                 os_free(bss->radius_server_clients);
    2597          26 :                 bss->radius_server_clients = os_strdup(pos);
    2598       14144 :         } else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
    2599          20 :                 bss->radius_server_auth_port = atoi(pos);
    2600       14124 :         } else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
    2601           7 :                 bss->radius_server_acct_port = atoi(pos);
    2602       14117 :         } else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
    2603           1 :                 bss->radius_server_ipv6 = atoi(pos);
    2604             : #endif /* RADIUS_SERVER */
    2605       14116 :         } else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
    2606           0 :                 bss->use_pae_group_addr = atoi(pos);
    2607       14116 :         } else if (os_strcmp(buf, "hw_mode") == 0) {
    2608        2447 :                 if (os_strcmp(pos, "a") == 0)
    2609         219 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
    2610        2228 :                 else if (os_strcmp(pos, "b") == 0)
    2611          18 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
    2612        2210 :                 else if (os_strcmp(pos, "g") == 0)
    2613        2209 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
    2614           1 :                 else if (os_strcmp(pos, "ad") == 0)
    2615           0 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
    2616           1 :                 else if (os_strcmp(pos, "any") == 0)
    2617           0 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
    2618             :                 else {
    2619           1 :                         wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
    2620             :                                    line, pos);
    2621           1 :                         return 1;
    2622             :                 }
    2623       11669 :         } else if (os_strcmp(buf, "wps_rf_bands") == 0) {
    2624           1 :                 if (os_strcmp(pos, "ad") == 0)
    2625           0 :                         bss->wps_rf_bands = WPS_RF_60GHZ;
    2626           1 :                 else if (os_strcmp(pos, "a") == 0)
    2627           0 :                         bss->wps_rf_bands = WPS_RF_50GHZ;
    2628           2 :                 else if (os_strcmp(pos, "g") == 0 ||
    2629           1 :                          os_strcmp(pos, "b") == 0)
    2630           0 :                         bss->wps_rf_bands = WPS_RF_24GHZ;
    2631           2 :                 else if (os_strcmp(pos, "ag") == 0 ||
    2632           1 :                          os_strcmp(pos, "ga") == 0)
    2633           0 :                         bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
    2634             :                 else {
    2635           1 :                         wpa_printf(MSG_ERROR,
    2636             :                                    "Line %d: unknown wps_rf_band '%s'",
    2637             :                                    line, pos);
    2638           1 :                         return 1;
    2639             :                 }
    2640       11668 :         } else if (os_strcmp(buf, "channel") == 0) {
    2641        2545 :                 if (os_strcmp(pos, "acs_survey") == 0) {
    2642             : #ifndef CONFIG_ACS
    2643             :                         wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled",
    2644             :                                    line);
    2645             :                         return 1;
    2646             : #else /* CONFIG_ACS */
    2647           0 :                         conf->acs = 1;
    2648           0 :                         conf->channel = 0;
    2649             : #endif /* CONFIG_ACS */
    2650             :                 } else {
    2651        2545 :                         conf->channel = atoi(pos);
    2652        2545 :                         conf->acs = conf->channel == 0;
    2653             :                 }
    2654        9123 :         } else if (os_strcmp(buf, "chanlist") == 0) {
    2655           6 :                 if (hostapd_parse_chanlist(conf, pos)) {
    2656           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
    2657             :                                    line);
    2658           0 :                         return 1;
    2659             :                 }
    2660        9117 :         } else if (os_strcmp(buf, "beacon_int") == 0) {
    2661          32 :                 int val = atoi(pos);
    2662             :                 /* MIB defines range as 1..65535, but very small values
    2663             :                  * cause problems with the current implementation.
    2664             :                  * Since it is unlikely that this small numbers are
    2665             :                  * useful in real life scenarios, do not allow beacon
    2666             :                  * period to be set below 15 TU. */
    2667          32 :                 if (val < 15 || val > 65535) {
    2668           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid beacon_int %d (expected 15..65535)",
    2669             :                                    line, val);
    2670           2 :                         return 1;
    2671             :                 }
    2672          30 :                 conf->beacon_int = val;
    2673             : #ifdef CONFIG_ACS
    2674        9085 :         } else if (os_strcmp(buf, "acs_num_scans") == 0) {
    2675           2 :                 int val = atoi(pos);
    2676           2 :                 if (val <= 0 || val > 100) {
    2677           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)",
    2678             :                                    line, val);
    2679           2 :                         return 1;
    2680             :                 }
    2681           0 :                 conf->acs_num_scans = val;
    2682        9083 :         } else if (os_strcmp(buf, "acs_chan_bias") == 0) {
    2683           1 :                 if (hostapd_config_parse_acs_chan_bias(conf, pos)) {
    2684           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias",
    2685             :                                    line);
    2686           0 :                         return -1;
    2687             :                 }
    2688             : #endif /* CONFIG_ACS */
    2689        9082 :         } else if (os_strcmp(buf, "dtim_period") == 0) {
    2690           0 :                 bss->dtim_period = atoi(pos);
    2691           0 :                 if (bss->dtim_period < 1 || bss->dtim_period > 255) {
    2692           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d",
    2693             :                                    line, bss->dtim_period);
    2694           0 :                         return 1;
    2695             :                 }
    2696        9082 :         } else if (os_strcmp(buf, "bss_load_update_period") == 0) {
    2697           1 :                 bss->bss_load_update_period = atoi(pos);
    2698           2 :                 if (bss->bss_load_update_period < 0 ||
    2699           1 :                     bss->bss_load_update_period > 100) {
    2700           0 :                         wpa_printf(MSG_ERROR,
    2701             :                                    "Line %d: invalid bss_load_update_period %d",
    2702             :                                    line, bss->bss_load_update_period);
    2703           0 :                         return 1;
    2704             :                 }
    2705        9081 :         } else if (os_strcmp(buf, "rts_threshold") == 0) {
    2706           3 :                 conf->rts_threshold = atoi(pos);
    2707           3 :                 if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) {
    2708           2 :                         wpa_printf(MSG_ERROR,
    2709             :                                    "Line %d: invalid rts_threshold %d",
    2710             :                                    line, conf->rts_threshold);
    2711           2 :                         return 1;
    2712             :                 }
    2713        9078 :         } else if (os_strcmp(buf, "fragm_threshold") == 0) {
    2714           5 :                 conf->fragm_threshold = atoi(pos);
    2715           5 :                 if (conf->fragm_threshold == -1) {
    2716             :                         /* allow a value of -1 */
    2717           9 :                 } else if (conf->fragm_threshold < 256 ||
    2718           4 :                            conf->fragm_threshold > 2346) {
    2719           2 :                         wpa_printf(MSG_ERROR,
    2720             :                                    "Line %d: invalid fragm_threshold %d",
    2721             :                                    line, conf->fragm_threshold);
    2722           2 :                         return 1;
    2723             :                 }
    2724        9073 :         } else if (os_strcmp(buf, "send_probe_response") == 0) {
    2725           2 :                 int val = atoi(pos);
    2726           2 :                 if (val != 0 && val != 1) {
    2727           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)",
    2728             :                                    line, val);
    2729           2 :                         return 1;
    2730             :                 }
    2731           0 :                 conf->send_probe_response = val;
    2732        9071 :         } else if (os_strcmp(buf, "supported_rates") == 0) {
    2733           2 :                 if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
    2734           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
    2735             :                                    line);
    2736           0 :                         return 1;
    2737             :                 }
    2738        9069 :         } else if (os_strcmp(buf, "basic_rates") == 0) {
    2739           1 :                 if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
    2740           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
    2741             :                                    line);
    2742           0 :                         return 1;
    2743             :                 }
    2744        9068 :         } else if (os_strcmp(buf, "preamble") == 0) {
    2745           1 :                 if (atoi(pos))
    2746           1 :                         conf->preamble = SHORT_PREAMBLE;
    2747             :                 else
    2748           0 :                         conf->preamble = LONG_PREAMBLE;
    2749        9067 :         } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
    2750          10 :                 bss->ignore_broadcast_ssid = atoi(pos);
    2751        9057 :         } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
    2752           1 :                 bss->no_probe_resp_if_max_sta = atoi(pos);
    2753        9056 :         } else if (os_strcmp(buf, "wep_default_key") == 0) {
    2754           1 :                 bss->ssid.wep.idx = atoi(pos);
    2755           1 :                 if (bss->ssid.wep.idx > 3) {
    2756           1 :                         wpa_printf(MSG_ERROR,
    2757             :                                    "Invalid wep_default_key index %d",
    2758           1 :                                    bss->ssid.wep.idx);
    2759           1 :                         return 1;
    2760             :                 }
    2761       18092 :         } else if (os_strcmp(buf, "wep_key0") == 0 ||
    2762       18072 :                    os_strcmp(buf, "wep_key1") == 0 ||
    2763       18070 :                    os_strcmp(buf, "wep_key2") == 0 ||
    2764        9035 :                    os_strcmp(buf, "wep_key3") == 0) {
    2765          36 :                 if (hostapd_config_read_wep(&bss->ssid.wep,
    2766          20 :                                             buf[7] - '0', pos)) {
    2767           4 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'",
    2768             :                                    line, buf);
    2769           4 :                         return 1;
    2770             :                 }
    2771             : #ifndef CONFIG_NO_VLAN
    2772        9035 :         } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
    2773          27 :                 bss->ssid.dynamic_vlan = atoi(pos);
    2774        9008 :         } else if (os_strcmp(buf, "per_sta_vif") == 0) {
    2775          10 :                 bss->ssid.per_sta_vif = atoi(pos);
    2776        8998 :         } else if (os_strcmp(buf, "vlan_file") == 0) {
    2777           6 :                 if (hostapd_config_read_vlan_file(bss, pos)) {
    2778           0 :                         wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
    2779             :                                    line, pos);
    2780           0 :                         return 1;
    2781             :                 }
    2782        8992 :         } else if (os_strcmp(buf, "vlan_naming") == 0) {
    2783          10 :                 bss->ssid.vlan_naming = atoi(pos);
    2784          19 :                 if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
    2785           9 :                     bss->ssid.vlan_naming < 0) {
    2786           2 :                         wpa_printf(MSG_ERROR,
    2787             :                                    "Line %d: invalid naming scheme %d",
    2788             :                                    line, bss->ssid.vlan_naming);
    2789           2 :                         return 1;
    2790             :                 }
    2791             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
    2792        8982 :         } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
    2793           5 :                 os_free(bss->ssid.vlan_tagged_interface);
    2794           5 :                 bss->ssid.vlan_tagged_interface = os_strdup(pos);
    2795             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    2796             : #endif /* CONFIG_NO_VLAN */
    2797        8977 :         } else if (os_strcmp(buf, "ap_table_max_size") == 0) {
    2798           3 :                 conf->ap_table_max_size = atoi(pos);
    2799        8974 :         } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
    2800           1 :                 conf->ap_table_expiration_time = atoi(pos);
    2801        8973 :         } else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
    2802          13 :                 if (hostapd_config_tx_queue(conf, buf, pos)) {
    2803           5 :                         wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
    2804             :                                    line);
    2805           5 :                         return 1;
    2806             :                 }
    2807       17920 :         } else if (os_strcmp(buf, "wme_enabled") == 0 ||
    2808        8960 :                    os_strcmp(buf, "wmm_enabled") == 0) {
    2809           9 :                 bss->wmm_enabled = atoi(pos);
    2810        8951 :         } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
    2811           0 :                 bss->wmm_uapsd = atoi(pos);
    2812       17902 :         } else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
    2813        8951 :                    os_strncmp(buf, "wmm_ac_", 7) == 0) {
    2814          72 :                 if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) {
    2815          12 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item",
    2816             :                                    line);
    2817          12 :                         return 1;
    2818             :                 }
    2819        8909 :         } else if (os_strcmp(buf, "bss") == 0) {
    2820          12 :                 if (hostapd_config_bss(conf, pos)) {
    2821           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid bss item",
    2822             :                                    line);
    2823           0 :                         return 1;
    2824             :                 }
    2825        8897 :         } else if (os_strcmp(buf, "bssid") == 0) {
    2826          93 :                 if (hwaddr_aton(pos, bss->bssid)) {
    2827           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid bssid item",
    2828             :                                    line);
    2829           0 :                         return 1;
    2830             :                 }
    2831        8804 :         } else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
    2832           0 :                 conf->use_driver_iface_addr = atoi(pos);
    2833             : #ifdef CONFIG_IEEE80211W
    2834        8804 :         } else if (os_strcmp(buf, "ieee80211w") == 0) {
    2835         237 :                 bss->ieee80211w = atoi(pos);
    2836        8567 :         } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
    2837          13 :                 if (os_strcmp(pos, "AES-128-CMAC") == 0) {
    2838           1 :                         bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
    2839          12 :                 } else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
    2840           5 :                         bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
    2841           7 :                 } else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
    2842           5 :                         bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
    2843           2 :                 } else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
    2844           1 :                         bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
    2845             :                 } else {
    2846           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
    2847             :                                    line, pos);
    2848           1 :                         return 1;
    2849             :                 }
    2850        8554 :         } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
    2851           2 :                 bss->assoc_sa_query_max_timeout = atoi(pos);
    2852           2 :                 if (bss->assoc_sa_query_max_timeout == 0) {
    2853           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout",
    2854             :                                    line);
    2855           1 :                         return 1;
    2856             :                 }
    2857        8552 :         } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) {
    2858           2 :                 bss->assoc_sa_query_retry_timeout = atoi(pos);
    2859           2 :                 if (bss->assoc_sa_query_retry_timeout == 0) {
    2860           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout",
    2861             :                                    line);
    2862           1 :                         return 1;
    2863             :                 }
    2864             : #endif /* CONFIG_IEEE80211W */
    2865             : #ifdef CONFIG_IEEE80211N
    2866        8550 :         } else if (os_strcmp(buf, "ieee80211n") == 0) {
    2867        2112 :                 conf->ieee80211n = atoi(pos);
    2868        6438 :         } else if (os_strcmp(buf, "ht_capab") == 0) {
    2869          82 :                 if (hostapd_config_ht_capab(conf, pos) < 0) {
    2870           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab",
    2871             :                                    line);
    2872           0 :                         return 1;
    2873             :                 }
    2874        6356 :         } else if (os_strcmp(buf, "require_ht") == 0) {
    2875           3 :                 conf->require_ht = atoi(pos);
    2876        6353 :         } else if (os_strcmp(buf, "obss_interval") == 0) {
    2877           5 :                 conf->obss_interval = atoi(pos);
    2878             : #endif /* CONFIG_IEEE80211N */
    2879             : #ifdef CONFIG_IEEE80211AC
    2880        6348 :         } else if (os_strcmp(buf, "ieee80211ac") == 0) {
    2881          29 :                 conf->ieee80211ac = atoi(pos);
    2882        6319 :         } else if (os_strcmp(buf, "vht_capab") == 0) {
    2883          16 :                 if (hostapd_config_vht_capab(conf, pos) < 0) {
    2884           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab",
    2885             :                                    line);
    2886           0 :                         return 1;
    2887             :                 }
    2888        6303 :         } else if (os_strcmp(buf, "require_vht") == 0) {
    2889           3 :                 conf->require_vht = atoi(pos);
    2890        6300 :         } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
    2891          30 :                 conf->vht_oper_chwidth = atoi(pos);
    2892        6270 :         } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
    2893          29 :                 conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
    2894        6241 :         } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) {
    2895           5 :                 conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
    2896        6236 :         } else if (os_strcmp(buf, "vendor_vht") == 0) {
    2897           1 :                 bss->vendor_vht = atoi(pos);
    2898        6235 :         } else if (os_strcmp(buf, "use_sta_nsts") == 0) {
    2899           1 :                 bss->use_sta_nsts = atoi(pos);
    2900             : #endif /* CONFIG_IEEE80211AC */
    2901        6234 :         } else if (os_strcmp(buf, "max_listen_interval") == 0) {
    2902           2 :                 bss->max_listen_interval = atoi(pos);
    2903        6232 :         } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
    2904          11 :                 bss->disable_pmksa_caching = atoi(pos);
    2905        6221 :         } else if (os_strcmp(buf, "okc") == 0) {
    2906           6 :                 bss->okc = atoi(pos);
    2907             : #ifdef CONFIG_WPS
    2908        6215 :         } else if (os_strcmp(buf, "wps_state") == 0) {
    2909         264 :                 bss->wps_state = atoi(pos);
    2910         264 :                 if (bss->wps_state < 0 || bss->wps_state > 2) {
    2911           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid wps_state",
    2912             :                                    line);
    2913           2 :                         return 1;
    2914             :                 }
    2915        5951 :         } else if (os_strcmp(buf, "wps_independent") == 0) {
    2916           4 :                 bss->wps_independent = atoi(pos);
    2917        5947 :         } else if (os_strcmp(buf, "ap_setup_locked") == 0) {
    2918           1 :                 bss->ap_setup_locked = atoi(pos);
    2919        5946 :         } else if (os_strcmp(buf, "uuid") == 0) {
    2920          48 :                 if (uuid_str2bin(pos, bss->uuid)) {
    2921           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
    2922           1 :                         return 1;
    2923             :                 }
    2924        5898 :         } else if (os_strcmp(buf, "wps_pin_requests") == 0) {
    2925           1 :                 os_free(bss->wps_pin_requests);
    2926           1 :                 bss->wps_pin_requests = os_strdup(pos);
    2927        5897 :         } else if (os_strcmp(buf, "device_name") == 0) {
    2928          38 :                 if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) {
    2929           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long "
    2930             :                                    "device_name", line);
    2931           1 :                         return 1;
    2932             :                 }
    2933          37 :                 os_free(bss->device_name);
    2934          37 :                 bss->device_name = os_strdup(pos);
    2935        5859 :         } else if (os_strcmp(buf, "manufacturer") == 0) {
    2936          38 :                 if (os_strlen(pos) > 64) {
    2937           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer",
    2938             :                                    line);
    2939           1 :                         return 1;
    2940             :                 }
    2941          37 :                 os_free(bss->manufacturer);
    2942          37 :                 bss->manufacturer = os_strdup(pos);
    2943        5821 :         } else if (os_strcmp(buf, "model_name") == 0) {
    2944          38 :                 if (os_strlen(pos) > 32) {
    2945           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long model_name",
    2946             :                                    line);
    2947           1 :                         return 1;
    2948             :                 }
    2949          37 :                 os_free(bss->model_name);
    2950          37 :                 bss->model_name = os_strdup(pos);
    2951        5783 :         } else if (os_strcmp(buf, "model_number") == 0) {
    2952          38 :                 if (os_strlen(pos) > 32) {
    2953           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long model_number",
    2954             :                                    line);
    2955           1 :                         return 1;
    2956             :                 }
    2957          37 :                 os_free(bss->model_number);
    2958          37 :                 bss->model_number = os_strdup(pos);
    2959        5745 :         } else if (os_strcmp(buf, "serial_number") == 0) {
    2960          38 :                 if (os_strlen(pos) > 32) {
    2961           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long serial_number",
    2962             :                                    line);
    2963           1 :                         return 1;
    2964             :                 }
    2965          37 :                 os_free(bss->serial_number);
    2966          37 :                 bss->serial_number = os_strdup(pos);
    2967        5707 :         } else if (os_strcmp(buf, "device_type") == 0) {
    2968          37 :                 if (wps_dev_type_str2bin(pos, bss->device_type))
    2969           1 :                         return 1;
    2970        5670 :         } else if (os_strcmp(buf, "config_methods") == 0) {
    2971          38 :                 os_free(bss->config_methods);
    2972          38 :                 bss->config_methods = os_strdup(pos);
    2973        5632 :         } else if (os_strcmp(buf, "os_version") == 0) {
    2974          37 :                 if (hexstr2bin(pos, bss->os_version, 4)) {
    2975           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid os_version",
    2976             :                                    line);
    2977           1 :                         return 1;
    2978             :                 }
    2979        5595 :         } else if (os_strcmp(buf, "ap_pin") == 0) {
    2980          68 :                 os_free(bss->ap_pin);
    2981          68 :                 bss->ap_pin = os_strdup(pos);
    2982        5527 :         } else if (os_strcmp(buf, "skip_cred_build") == 0) {
    2983           4 :                 bss->skip_cred_build = atoi(pos);
    2984        5523 :         } else if (os_strcmp(buf, "extra_cred") == 0) {
    2985           4 :                 os_free(bss->extra_cred);
    2986           4 :                 bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len);
    2987           4 :                 if (bss->extra_cred == NULL) {
    2988           0 :                         wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'",
    2989             :                                    line, pos);
    2990           0 :                         return 1;
    2991             :                 }
    2992        5519 :         } else if (os_strcmp(buf, "wps_cred_processing") == 0) {
    2993           3 :                 bss->wps_cred_processing = atoi(pos);
    2994        5516 :         } else if (os_strcmp(buf, "ap_settings") == 0) {
    2995           2 :                 os_free(bss->ap_settings);
    2996           2 :                 bss->ap_settings =
    2997           2 :                         (u8 *) os_readfile(pos, &bss->ap_settings_len);
    2998           2 :                 if (bss->ap_settings == NULL) {
    2999           1 :                         wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'",
    3000             :                                    line, pos);
    3001           1 :                         return 1;
    3002             :                 }
    3003        5514 :         } else if (os_strcmp(buf, "upnp_iface") == 0) {
    3004          36 :                 os_free(bss->upnp_iface);
    3005          36 :                 bss->upnp_iface = os_strdup(pos);
    3006        5478 :         } else if (os_strcmp(buf, "friendly_name") == 0) {
    3007          15 :                 os_free(bss->friendly_name);
    3008          15 :                 bss->friendly_name = os_strdup(pos);
    3009        5463 :         } else if (os_strcmp(buf, "manufacturer_url") == 0) {
    3010          13 :                 os_free(bss->manufacturer_url);
    3011          13 :                 bss->manufacturer_url = os_strdup(pos);
    3012        5450 :         } else if (os_strcmp(buf, "model_description") == 0) {
    3013          13 :                 os_free(bss->model_description);
    3014          13 :                 bss->model_description = os_strdup(pos);
    3015        5437 :         } else if (os_strcmp(buf, "model_url") == 0) {
    3016          13 :                 os_free(bss->model_url);
    3017          13 :                 bss->model_url = os_strdup(pos);
    3018        5424 :         } else if (os_strcmp(buf, "upc") == 0) {
    3019          13 :                 os_free(bss->upc);
    3020          13 :                 bss->upc = os_strdup(pos);
    3021        5411 :         } else if (os_strcmp(buf, "pbc_in_m1") == 0) {
    3022           0 :                 bss->pbc_in_m1 = atoi(pos);
    3023        5411 :         } else if (os_strcmp(buf, "server_id") == 0) {
    3024          13 :                 os_free(bss->server_id);
    3025          13 :                 bss->server_id = os_strdup(pos);
    3026             : #ifdef CONFIG_WPS_NFC
    3027        5398 :         } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
    3028           2 :                 bss->wps_nfc_dev_pw_id = atoi(pos);
    3029           3 :                 if (bss->wps_nfc_dev_pw_id < 0x10 ||
    3030           1 :                     bss->wps_nfc_dev_pw_id > 0xffff) {
    3031           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value",
    3032             :                                    line);
    3033           2 :                         return 1;
    3034             :                 }
    3035           0 :                 bss->wps_nfc_pw_from_config = 1;
    3036        5396 :         } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
    3037           1 :                 wpabuf_free(bss->wps_nfc_dh_pubkey);
    3038           1 :                 bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos);
    3039           1 :                 bss->wps_nfc_pw_from_config = 1;
    3040        5395 :         } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
    3041           1 :                 wpabuf_free(bss->wps_nfc_dh_privkey);
    3042           1 :                 bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos);
    3043           1 :                 bss->wps_nfc_pw_from_config = 1;
    3044        5394 :         } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
    3045           1 :                 wpabuf_free(bss->wps_nfc_dev_pw);
    3046           1 :                 bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos);
    3047           1 :                 bss->wps_nfc_pw_from_config = 1;
    3048             : #endif /* CONFIG_WPS_NFC */
    3049             : #endif /* CONFIG_WPS */
    3050             : #ifdef CONFIG_P2P_MANAGER
    3051        5393 :         } else if (os_strcmp(buf, "manage_p2p") == 0) {
    3052           5 :                 if (atoi(pos))
    3053           4 :                         bss->p2p |= P2P_MANAGE;
    3054             :                 else
    3055           1 :                         bss->p2p &= ~P2P_MANAGE;
    3056        5388 :         } else if (os_strcmp(buf, "allow_cross_connection") == 0) {
    3057           3 :                 if (atoi(pos))
    3058           1 :                         bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
    3059             :                 else
    3060           2 :                         bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
    3061             : #endif /* CONFIG_P2P_MANAGER */
    3062        5385 :         } else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
    3063           1 :                 bss->disassoc_low_ack = atoi(pos);
    3064        5384 :         } else if (os_strcmp(buf, "tdls_prohibit") == 0) {
    3065           1 :                 if (atoi(pos))
    3066           0 :                         bss->tdls |= TDLS_PROHIBIT;
    3067             :                 else
    3068           1 :                         bss->tdls &= ~TDLS_PROHIBIT;
    3069        5383 :         } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
    3070           1 :                 if (atoi(pos))
    3071           0 :                         bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
    3072             :                 else
    3073           1 :                         bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
    3074             : #ifdef CONFIG_RSN_TESTING
    3075             :         } else if (os_strcmp(buf, "rsn_testing") == 0) {
    3076             :                 extern int rsn_testing;
    3077             :                 rsn_testing = atoi(pos);
    3078             : #endif /* CONFIG_RSN_TESTING */
    3079        5382 :         } else if (os_strcmp(buf, "time_advertisement") == 0) {
    3080           6 :                 bss->time_advertisement = atoi(pos);
    3081        5376 :         } else if (os_strcmp(buf, "time_zone") == 0) {
    3082           7 :                 size_t tz_len = os_strlen(pos);
    3083           7 :                 if (tz_len < 4 || tz_len > 255) {
    3084           1 :                         wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone",
    3085             :                                    line);
    3086           1 :                         return 1;
    3087             :                 }
    3088           6 :                 os_free(bss->time_zone);
    3089           6 :                 bss->time_zone = os_strdup(pos);
    3090           6 :                 if (bss->time_zone == NULL)
    3091           0 :                         return 1;
    3092             : #ifdef CONFIG_WNM
    3093        5369 :         } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
    3094          10 :                 bss->wnm_sleep_mode = atoi(pos);
    3095        5359 :         } else if (os_strcmp(buf, "bss_transition") == 0) {
    3096          36 :                 bss->bss_transition = atoi(pos);
    3097             : #endif /* CONFIG_WNM */
    3098             : #ifdef CONFIG_INTERWORKING
    3099        5323 :         } else if (os_strcmp(buf, "interworking") == 0) {
    3100         201 :                 bss->interworking = atoi(pos);
    3101        5122 :         } else if (os_strcmp(buf, "access_network_type") == 0) {
    3102         200 :                 bss->access_network_type = atoi(pos);
    3103         399 :                 if (bss->access_network_type < 0 ||
    3104         199 :                     bss->access_network_type > 15) {
    3105           2 :                         wpa_printf(MSG_ERROR,
    3106             :                                    "Line %d: invalid access_network_type",
    3107             :                                    line);
    3108           2 :                         return 1;
    3109             :                 }
    3110        4922 :         } else if (os_strcmp(buf, "internet") == 0) {
    3111         197 :                 bss->internet = atoi(pos);
    3112        4725 :         } else if (os_strcmp(buf, "asra") == 0) {
    3113         198 :                 bss->asra = atoi(pos);
    3114        4527 :         } else if (os_strcmp(buf, "esr") == 0) {
    3115         198 :                 bss->esr = atoi(pos);
    3116        4329 :         } else if (os_strcmp(buf, "uesa") == 0) {
    3117         198 :                 bss->uesa = atoi(pos);
    3118        4131 :         } else if (os_strcmp(buf, "venue_group") == 0) {
    3119         197 :                 bss->venue_group = atoi(pos);
    3120         197 :                 bss->venue_info_set = 1;
    3121        3934 :         } else if (os_strcmp(buf, "venue_type") == 0) {
    3122         197 :                 bss->venue_type = atoi(pos);
    3123         197 :                 bss->venue_info_set = 1;
    3124        3737 :         } else if (os_strcmp(buf, "hessid") == 0) {
    3125         110 :                 if (hwaddr_aton(pos, bss->hessid)) {
    3126           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line);
    3127           1 :                         return 1;
    3128             :                 }
    3129        3627 :         } else if (os_strcmp(buf, "roaming_consortium") == 0) {
    3130         767 :                 if (parse_roaming_consortium(bss, pos, line) < 0)
    3131           3 :                         return 1;
    3132        2860 :         } else if (os_strcmp(buf, "venue_name") == 0) {
    3133         401 :                 if (parse_venue_name(bss, pos, line) < 0)
    3134           6 :                         return 1;
    3135        2459 :         } else if (os_strcmp(buf, "network_auth_type") == 0) {
    3136             :                 u8 auth_type;
    3137             :                 u16 redirect_url_len;
    3138          39 :                 if (hexstr2bin(pos, &auth_type, 1)) {
    3139           1 :                         wpa_printf(MSG_ERROR,
    3140             :                                    "Line %d: Invalid network_auth_type '%s'",
    3141             :                                    line, pos);
    3142           2 :                         return 1;
    3143             :                 }
    3144          38 :                 if (auth_type == 0 || auth_type == 2)
    3145          37 :                         redirect_url_len = os_strlen(pos + 2);
    3146             :                 else
    3147           1 :                         redirect_url_len = 0;
    3148          38 :                 os_free(bss->network_auth_type);
    3149          38 :                 bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1);
    3150          38 :                 if (bss->network_auth_type == NULL)
    3151           0 :                         return 1;
    3152          38 :                 *bss->network_auth_type = auth_type;
    3153          38 :                 WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len);
    3154          38 :                 if (redirect_url_len)
    3155          37 :                         os_memcpy(bss->network_auth_type + 3, pos + 2,
    3156             :                                   redirect_url_len);
    3157          38 :                 bss->network_auth_type_len = 3 + redirect_url_len;
    3158        2420 :         } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
    3159          38 :                 if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) {
    3160           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'",
    3161             :                                    line, pos);
    3162           1 :                         bss->ipaddr_type_configured = 0;
    3163           1 :                         return 1;
    3164             :                 }
    3165          37 :                 bss->ipaddr_type_configured = 1;
    3166        2382 :         } else if (os_strcmp(buf, "domain_name") == 0) {
    3167         191 :                 int j, num_domains, domain_len, domain_list_len = 0;
    3168             :                 char *tok_start, *tok_prev;
    3169             :                 u8 *domain_list, *domain_ptr;
    3170             : 
    3171         191 :                 domain_list_len = os_strlen(pos) + 1;
    3172         191 :                 domain_list = os_malloc(domain_list_len);
    3173         191 :                 if (domain_list == NULL)
    3174           0 :                         return 1;
    3175             : 
    3176         191 :                 domain_ptr = domain_list;
    3177         191 :                 tok_prev = pos;
    3178         191 :                 num_domains = 1;
    3179         550 :                 while ((tok_prev = os_strchr(tok_prev, ','))) {
    3180         168 :                         num_domains++;
    3181         168 :                         tok_prev++;
    3182             :                 }
    3183         191 :                 tok_prev = pos;
    3184         550 :                 for (j = 0; j < num_domains; j++) {
    3185         359 :                         tok_start = os_strchr(tok_prev, ',');
    3186         359 :                         if (tok_start) {
    3187         168 :                                 domain_len = tok_start - tok_prev;
    3188         168 :                                 *domain_ptr = domain_len;
    3189         168 :                                 os_memcpy(domain_ptr + 1, tok_prev, domain_len);
    3190         168 :                                 domain_ptr += domain_len + 1;
    3191         168 :                                 tok_prev = ++tok_start;
    3192             :                         } else {
    3193         191 :                                 domain_len = os_strlen(tok_prev);
    3194         191 :                                 *domain_ptr = domain_len;
    3195         191 :                                 os_memcpy(domain_ptr + 1, tok_prev, domain_len);
    3196         191 :                                 domain_ptr += domain_len + 1;
    3197             :                         }
    3198             :                 }
    3199             : 
    3200         191 :                 os_free(bss->domain_name);
    3201         191 :                 bss->domain_name = domain_list;
    3202         191 :                 bss->domain_name_len = domain_list_len;
    3203        2191 :         } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
    3204         201 :                 if (parse_3gpp_cell_net(bss, pos, line) < 0)
    3205           6 :                         return 1;
    3206        1990 :         } else if (os_strcmp(buf, "nai_realm") == 0) {
    3207         357 :                 if (parse_nai_realm(bss, pos, line) < 0)
    3208           7 :                         return 1;
    3209        1633 :         } else if (os_strcmp(buf, "anqp_elem") == 0) {
    3210          34 :                 if (parse_anqp_elem(bss, pos, line) < 0)
    3211           0 :                         return 1;
    3212        1599 :         } else if (os_strcmp(buf, "gas_frag_limit") == 0) {
    3213           0 :                 bss->gas_frag_limit = atoi(pos);
    3214        1599 :         } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
    3215           5 :                 bss->gas_comeback_delay = atoi(pos);
    3216        1594 :         } else if (os_strcmp(buf, "qos_map_set") == 0) {
    3217           7 :                 if (parse_qos_map_set(bss, pos, line) < 0)
    3218           6 :                         return 1;
    3219             : #endif /* CONFIG_INTERWORKING */
    3220             : #ifdef CONFIG_RADIUS_TEST
    3221             :         } else if (os_strcmp(buf, "dump_msk_file") == 0) {
    3222             :                 os_free(bss->dump_msk_file);
    3223             :                 bss->dump_msk_file = os_strdup(pos);
    3224             : #endif /* CONFIG_RADIUS_TEST */
    3225             : #ifdef CONFIG_PROXYARP
    3226        1587 :         } else if (os_strcmp(buf, "proxy_arp") == 0) {
    3227          12 :                 bss->proxy_arp = atoi(pos);
    3228             : #endif /* CONFIG_PROXYARP */
    3229             : #ifdef CONFIG_HS20
    3230        1575 :         } else if (os_strcmp(buf, "hs20") == 0) {
    3231         198 :                 bss->hs20 = atoi(pos);
    3232        1377 :         } else if (os_strcmp(buf, "disable_dgaf") == 0) {
    3233          14 :                 bss->disable_dgaf = atoi(pos);
    3234        1363 :         } else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
    3235           2 :                 bss->na_mcast_to_ucast = atoi(pos);
    3236        1361 :         } else if (os_strcmp(buf, "osen") == 0) {
    3237           1 :                 bss->osen = atoi(pos);
    3238        1360 :         } else if (os_strcmp(buf, "anqp_domain_id") == 0) {
    3239           0 :                 bss->anqp_domain_id = atoi(pos);
    3240        1360 :         } else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
    3241           1 :                 bss->hs20_deauth_req_timeout = atoi(pos);
    3242        1359 :         } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
    3243          75 :                 if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
    3244           1 :                         return 1;
    3245        1284 :         } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
    3246         205 :                 if (hs20_parse_wan_metrics(bss, pos, line) < 0)
    3247           6 :                         return 1;
    3248        1079 :         } else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
    3249         592 :                 if (hs20_parse_conn_capab(bss, pos, line) < 0) {
    3250           2 :                         return 1;
    3251             :                 }
    3252         487 :         } else if (os_strcmp(buf, "hs20_operating_class") == 0) {
    3253             :                 u8 *oper_class;
    3254             :                 size_t oper_class_len;
    3255         199 :                 oper_class_len = os_strlen(pos);
    3256         199 :                 if (oper_class_len < 2 || (oper_class_len & 0x01)) {
    3257           1 :                         wpa_printf(MSG_ERROR,
    3258             :                                    "Line %d: Invalid hs20_operating_class '%s'",
    3259             :                                    line, pos);
    3260           1 :                         return 1;
    3261             :                 }
    3262         198 :                 oper_class_len /= 2;
    3263         198 :                 oper_class = os_malloc(oper_class_len);
    3264         198 :                 if (oper_class == NULL)
    3265           0 :                         return 1;
    3266         198 :                 if (hexstr2bin(pos, oper_class, oper_class_len)) {
    3267           1 :                         wpa_printf(MSG_ERROR,
    3268             :                                    "Line %d: Invalid hs20_operating_class '%s'",
    3269             :                                    line, pos);
    3270           1 :                         os_free(oper_class);
    3271           1 :                         return 1;
    3272             :                 }
    3273         197 :                 os_free(bss->hs20_operating_class);
    3274         197 :                 bss->hs20_operating_class = oper_class;
    3275         197 :                 bss->hs20_operating_class_len = oper_class_len;
    3276         288 :         } else if (os_strcmp(buf, "hs20_icon") == 0) {
    3277          19 :                 if (hs20_parse_icon(bss, pos) < 0) {
    3278           7 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
    3279             :                                    line, pos);
    3280           7 :                         return 1;
    3281             :                 }
    3282         269 :         } else if (os_strcmp(buf, "osu_ssid") == 0) {
    3283          13 :                 if (hs20_parse_osu_ssid(bss, pos, line) < 0)
    3284           4 :                         return 1;
    3285         256 :         } else if (os_strcmp(buf, "osu_server_uri") == 0) {
    3286          10 :                 if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
    3287           0 :                         return 1;
    3288         246 :         } else if (os_strcmp(buf, "osu_friendly_name") == 0) {
    3289          21 :                 if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
    3290           2 :                         return 1;
    3291         225 :         } else if (os_strcmp(buf, "osu_nai") == 0) {
    3292           2 :                 if (hs20_parse_osu_nai(bss, pos, line) < 0)
    3293           1 :                         return 1;
    3294         223 :         } else if (os_strcmp(buf, "osu_method_list") == 0) {
    3295          10 :                 if (hs20_parse_osu_method_list(bss, pos, line) < 0)
    3296           1 :                         return 1;
    3297         213 :         } else if (os_strcmp(buf, "osu_icon") == 0) {
    3298          13 :                 if (hs20_parse_osu_icon(bss, pos, line) < 0)
    3299           1 :                         return 1;
    3300         200 :         } else if (os_strcmp(buf, "osu_service_desc") == 0) {
    3301          20 :                 if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
    3302           2 :                         return 1;
    3303         180 :         } else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
    3304           1 :                 os_free(bss->subscr_remediation_url);
    3305           1 :                 bss->subscr_remediation_url = os_strdup(pos);
    3306         179 :         } else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
    3307           1 :                 bss->subscr_remediation_method = atoi(pos);
    3308             : #endif /* CONFIG_HS20 */
    3309             : #ifdef CONFIG_MBO
    3310         178 :         } else if (os_strcmp(buf, "mbo") == 0) {
    3311          11 :                 bss->mbo_enabled = atoi(pos);
    3312             : #endif /* CONFIG_MBO */
    3313             : #ifdef CONFIG_TESTING_OPTIONS
    3314             : #define PARSE_TEST_PROBABILITY(_val)                            \
    3315             :         } else if (os_strcmp(buf, #_val) == 0) {                \
    3316             :                 char *end;                                      \
    3317             :                                                                 \
    3318             :                 conf->_val = strtod(pos, &end);                  \
    3319             :                 if (*end || conf->_val < 0.0 ||                   \
    3320             :                     conf->_val > 1.0) {                           \
    3321             :                         wpa_printf(MSG_ERROR,                   \
    3322             :                                    "Line %d: Invalid value '%s'", \
    3323             :                                    line, pos);                  \
    3324             :                         return 1;                               \
    3325             :                 }
    3326         167 :         PARSE_TEST_PROBABILITY(ignore_probe_probability)
    3327         166 :         PARSE_TEST_PROBABILITY(ignore_auth_probability)
    3328         165 :         PARSE_TEST_PROBABILITY(ignore_assoc_probability)
    3329         164 :         PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
    3330         163 :         PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
    3331         163 :         } else if (os_strcmp(buf, "ecsa_ie_only") == 0) {
    3332           1 :                 conf->ecsa_ie_only = atoi(pos);
    3333         162 :         } else if (os_strcmp(buf, "bss_load_test") == 0) {
    3334          10 :                 WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
    3335          10 :                 pos = os_strchr(pos, ':');
    3336          10 :                 if (pos == NULL) {
    3337           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
    3338             :                                    line);
    3339           2 :                         return 1;
    3340             :                 }
    3341           8 :                 pos++;
    3342           8 :                 bss->bss_load_test[2] = atoi(pos);
    3343           8 :                 pos = os_strchr(pos, ':');
    3344           8 :                 if (pos == NULL) {
    3345           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
    3346             :                                    line);
    3347           1 :                         return 1;
    3348             :                 }
    3349           7 :                 pos++;
    3350           7 :                 WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
    3351           7 :                 bss->bss_load_test_set = 1;
    3352         152 :         } else if (os_strcmp(buf, "radio_measurements") == 0) {
    3353             :                 /*
    3354             :                  * DEPRECATED: This parameter will be removed in the future.
    3355             :                  * Use rrm_neighbor_report instead.
    3356             :                  */
    3357           0 :                 int val = atoi(pos);
    3358             : 
    3359           0 :                 if (val & BIT(0))
    3360           0 :                         bss->radio_measurements[0] |=
    3361             :                                 WLAN_RRM_CAPS_NEIGHBOR_REPORT;
    3362         152 :         } else if (os_strcmp(buf, "own_ie_override") == 0) {
    3363             :                 struct wpabuf *tmp;
    3364          22 :                 size_t len = os_strlen(pos) / 2;
    3365             : 
    3366          22 :                 tmp = wpabuf_alloc(len);
    3367          22 :                 if (!tmp)
    3368           0 :                         return 1;
    3369             : 
    3370          22 :                 if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
    3371           1 :                         wpabuf_free(tmp);
    3372           1 :                         wpa_printf(MSG_ERROR,
    3373             :                                    "Line %d: Invalid own_ie_override '%s'",
    3374             :                                    line, pos);
    3375           1 :                         return 1;
    3376             :                 }
    3377             : 
    3378          21 :                 wpabuf_free(bss->own_ie_override);
    3379          21 :                 bss->own_ie_override = tmp;
    3380             : #endif /* CONFIG_TESTING_OPTIONS */
    3381         130 :         } else if (os_strcmp(buf, "vendor_elements") == 0) {
    3382          16 :                 if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
    3383           2 :                         return 1;
    3384         114 :         } else if (os_strcmp(buf, "assocresp_elements") == 0) {
    3385           3 :                 if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
    3386           2 :                         return 1;
    3387         111 :         } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
    3388           3 :                 bss->sae_anti_clogging_threshold = atoi(pos);
    3389         108 :         } else if (os_strcmp(buf, "sae_groups") == 0) {
    3390           5 :                 if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
    3391           0 :                         wpa_printf(MSG_ERROR,
    3392             :                                    "Line %d: Invalid sae_groups value '%s'",
    3393             :                                    line, pos);
    3394           0 :                         return 1;
    3395             :                 }
    3396         103 :         } else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
    3397           5 :                 int val = atoi(pos);
    3398           5 :                 if (val < 0 || val > 255) {
    3399           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
    3400             :                                    line, val);
    3401           2 :                         return 1;
    3402             :                 }
    3403           3 :                 conf->local_pwr_constraint = val;
    3404          98 :         } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
    3405           2 :                 conf->spectrum_mgmt_required = atoi(pos);
    3406          96 :         } else if (os_strcmp(buf, "wowlan_triggers") == 0) {
    3407           0 :                 os_free(bss->wowlan_triggers);
    3408           0 :                 bss->wowlan_triggers = os_strdup(pos);
    3409             : #ifdef CONFIG_FST
    3410          96 :         } else if (os_strcmp(buf, "fst_group_id") == 0) {
    3411          25 :                 size_t len = os_strlen(pos);
    3412             : 
    3413          25 :                 if (!len || len >= sizeof(conf->fst_cfg.group_id)) {
    3414           1 :                         wpa_printf(MSG_ERROR,
    3415             :                                    "Line %d: Invalid fst_group_id value '%s'",
    3416             :                                    line, pos);
    3417           1 :                         return 1;
    3418             :                 }
    3419             : 
    3420          24 :                 if (conf->fst_cfg.group_id[0]) {
    3421           0 :                         wpa_printf(MSG_ERROR,
    3422             :                                    "Line %d: Duplicate fst_group value '%s'",
    3423             :                                    line, pos);
    3424           0 :                         return 1;
    3425             :                 }
    3426             : 
    3427          24 :                 os_strlcpy(conf->fst_cfg.group_id, pos,
    3428             :                            sizeof(conf->fst_cfg.group_id));
    3429          71 :         } else if (os_strcmp(buf, "fst_priority") == 0) {
    3430             :                 char *endp;
    3431             :                 long int val;
    3432             : 
    3433          25 :                 if (!*pos) {
    3434           0 :                         wpa_printf(MSG_ERROR,
    3435             :                                    "Line %d: fst_priority value not supplied (expected 1..%u)",
    3436             :                                    line, FST_MAX_PRIO_VALUE);
    3437           4 :                         return -1;
    3438             :                 }
    3439             : 
    3440          25 :                 val = strtol(pos, &endp, 0);
    3441          25 :                 if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) {
    3442           4 :                         wpa_printf(MSG_ERROR,
    3443             :                                    "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)",
    3444             :                                    line, val, pos, FST_MAX_PRIO_VALUE);
    3445           4 :                         return 1;
    3446             :                 }
    3447          21 :                 conf->fst_cfg.priority = (u8) val;
    3448          46 :         } else if (os_strcmp(buf, "fst_llt") == 0) {
    3449             :                 char *endp;
    3450             :                 long int val;
    3451             : 
    3452          21 :                 if (!*pos) {
    3453           0 :                         wpa_printf(MSG_ERROR,
    3454             :                                    "Line %d: fst_llt value not supplied (expected 1..%u)",
    3455             :                                    line, FST_MAX_LLT_MS);
    3456           4 :                         return -1;
    3457             :                 }
    3458          21 :                 val = strtol(pos, &endp, 0);
    3459          39 :                 if (*endp || val < 1 ||
    3460          18 :                     (unsigned long int) val > FST_MAX_LLT_MS) {
    3461           4 :                         wpa_printf(MSG_ERROR,
    3462             :                                    "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
    3463             :                                    line, val, pos, FST_MAX_LLT_MS);
    3464           4 :                         return 1;
    3465             :                 }
    3466          17 :                 conf->fst_cfg.llt = (u32) val;
    3467             : #endif /* CONFIG_FST */
    3468          25 :         } else if (os_strcmp(buf, "track_sta_max_num") == 0) {
    3469           9 :                 conf->track_sta_max_num = atoi(pos);
    3470          16 :         } else if (os_strcmp(buf, "track_sta_max_age") == 0) {
    3471           1 :                 conf->track_sta_max_age = atoi(pos);
    3472          15 :         } else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) {
    3473           3 :                 os_free(bss->no_probe_resp_if_seen_on);
    3474           3 :                 bss->no_probe_resp_if_seen_on = os_strdup(pos);
    3475          12 :         } else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
    3476           4 :                 os_free(bss->no_auth_if_seen_on);
    3477           4 :                 bss->no_auth_if_seen_on = os_strdup(pos);
    3478           8 :         } else if (os_strcmp(buf, "lci") == 0) {
    3479           0 :                 wpabuf_free(conf->lci);
    3480           0 :                 conf->lci = wpabuf_parse_bin(pos);
    3481           8 :         } else if (os_strcmp(buf, "civic") == 0) {
    3482           0 :                 wpabuf_free(conf->civic);
    3483           0 :                 conf->civic = wpabuf_parse_bin(pos);
    3484           8 :         } else if (os_strcmp(buf, "rrm_neighbor_report") == 0) {
    3485           4 :                 if (atoi(pos))
    3486           4 :                         bss->radio_measurements[0] |=
    3487             :                                 WLAN_RRM_CAPS_NEIGHBOR_REPORT;
    3488           4 :         } else if (os_strcmp(buf, "gas_address3") == 0) {
    3489           2 :                 bss->gas_address3 = atoi(pos);
    3490           2 :         } else if (os_strcmp(buf, "ftm_responder") == 0) {
    3491           1 :                 bss->ftm_responder = atoi(pos);
    3492           1 :         } else if (os_strcmp(buf, "ftm_initiator") == 0) {
    3493           1 :                 bss->ftm_initiator = atoi(pos);
    3494             :         } else {
    3495           0 :                 wpa_printf(MSG_ERROR,
    3496             :                            "Line %d: unknown configuration item '%s'",
    3497             :                            line, buf);
    3498           0 :                 return 1;
    3499             :         }
    3500             : 
    3501       31756 :         return 0;
    3502             : }
    3503             : 
    3504             : 
    3505             : /**
    3506             :  * hostapd_config_read - Read and parse a configuration file
    3507             :  * @fname: Configuration file name (including path, if needed)
    3508             :  * Returns: Allocated configuration data structure
    3509             :  */
    3510          96 : struct hostapd_config * hostapd_config_read(const char *fname)
    3511             : {
    3512             :         struct hostapd_config *conf;
    3513             :         FILE *f;
    3514             :         char buf[4096], *pos;
    3515          96 :         int line = 0;
    3516          96 :         int errors = 0;
    3517             :         size_t i;
    3518             : 
    3519          96 :         f = fopen(fname, "r");
    3520          96 :         if (f == NULL) {
    3521           0 :                 wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
    3522             :                            "for reading.", fname);
    3523           0 :                 return NULL;
    3524             :         }
    3525             : 
    3526          96 :         conf = hostapd_config_defaults();
    3527          96 :         if (conf == NULL) {
    3528           1 :                 fclose(f);
    3529           1 :                 return NULL;
    3530             :         }
    3531             : 
    3532             :         /* set default driver based on configuration */
    3533          95 :         conf->driver = wpa_drivers[0];
    3534          95 :         if (conf->driver == NULL) {
    3535           0 :                 wpa_printf(MSG_ERROR, "No driver wrappers registered!");
    3536           0 :                 hostapd_config_free(conf);
    3537           0 :                 fclose(f);
    3538           0 :                 return NULL;
    3539             :         }
    3540             : 
    3541          95 :         conf->last_bss = conf->bss[0];
    3542             : 
    3543        1398 :         while (fgets(buf, sizeof(buf), f)) {
    3544             :                 struct hostapd_bss_config *bss;
    3545             : 
    3546        1208 :                 bss = conf->last_bss;
    3547        1208 :                 line++;
    3548             : 
    3549        1208 :                 if (buf[0] == '#')
    3550           4 :                         continue;
    3551        1204 :                 pos = buf;
    3552       23127 :                 while (*pos != '\0') {
    3553       21923 :                         if (*pos == '\n') {
    3554        1204 :                                 *pos = '\0';
    3555        1204 :                                 break;
    3556             :                         }
    3557       20719 :                         pos++;
    3558             :                 }
    3559        1204 :                 if (buf[0] == '\0')
    3560         156 :                         continue;
    3561             : 
    3562        1048 :                 pos = os_strchr(buf, '=');
    3563        1048 :                 if (pos == NULL) {
    3564           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
    3565             :                                    line, buf);
    3566           0 :                         errors++;
    3567           0 :                         continue;
    3568             :                 }
    3569        1048 :                 *pos = '\0';
    3570        1048 :                 pos++;
    3571        1048 :                 errors += hostapd_config_fill(conf, bss, buf, pos, line);
    3572             :         }
    3573             : 
    3574          95 :         fclose(f);
    3575             : 
    3576         198 :         for (i = 0; i < conf->num_bss; i++)
    3577         103 :                 hostapd_set_security_params(conf->bss[i], 1);
    3578             : 
    3579          95 :         if (hostapd_config_check(conf, 1))
    3580           0 :                 errors++;
    3581             : 
    3582             : #ifndef WPA_IGNORE_CONFIG_ERRORS
    3583          95 :         if (errors) {
    3584           9 :                 wpa_printf(MSG_ERROR, "%d errors found in configuration file "
    3585             :                            "'%s'", errors, fname);
    3586           9 :                 hostapd_config_free(conf);
    3587           9 :                 conf = NULL;
    3588             :         }
    3589             : #endif /* WPA_IGNORE_CONFIG_ERRORS */
    3590             : 
    3591          95 :         return conf;
    3592             : }
    3593             : 
    3594             : 
    3595       30904 : int hostapd_set_iface(struct hostapd_config *conf,
    3596             :                       struct hostapd_bss_config *bss, const char *field,
    3597             :                       char *value)
    3598             : {
    3599             :         int errors;
    3600             :         size_t i;
    3601             : 
    3602       30904 :         errors = hostapd_config_fill(conf, bss, field, value, 0);
    3603       30904 :         if (errors) {
    3604         175 :                 wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
    3605             :                            "to value '%s'", field, value);
    3606         175 :                 return -1;
    3607             :         }
    3608             : 
    3609       61466 :         for (i = 0; i < conf->num_bss; i++)
    3610       30737 :                 hostapd_set_security_params(conf->bss[i], 0);
    3611             : 
    3612       30729 :         if (hostapd_config_check(conf, 0)) {
    3613           1 :                 wpa_printf(MSG_ERROR, "Configuration check failed");
    3614           1 :                 return -1;
    3615             :         }
    3616             : 
    3617       30728 :         return 0;
    3618             : }

Generated by: LCOV version 1.10