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

Generated by: LCOV version 1.10