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 1422976643 Lines: 1932 2175 88.8 %
Date: 2015-02-03 Functions: 40 40 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         428 : 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         428 :         nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv));
     541         428 :         if (nserv == NULL)
     542           2 :                 return -1;
     543             : 
     544         426 :         *server = nserv;
     545         426 :         nserv = &nserv[*num_server];
     546         426 :         (*num_server)++;
     547         426 :         (*curr_serv) = nserv;
     548             : 
     549         426 :         os_memset(nserv, 0, sizeof(*nserv));
     550         426 :         nserv->port = def_port;
     551         426 :         ret = hostapd_parse_ip_addr(val, &nserv->addr);
     552         426 :         nserv->index = server_index++;
     553             : 
     554         426 :         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         657 : static int hostapd_config_parse_key_mgmt(int line, const char *value)
     654             : {
     655         657 :         int val = 0, last;
     656             :         char *start, *end, *buf;
     657             : 
     658         657 :         buf = os_strdup(value);
     659         657 :         if (buf == NULL)
     660           4 :                 return -1;
     661         653 :         start = buf;
     662             : 
     663        1319 :         while (*start != '\0') {
     664        1343 :                 while (*start == ' ' || *start == '\t')
     665          11 :                         start++;
     666         666 :                 if (*start == '\0')
     667           1 :                         break;
     668         665 :                 end = start;
     669        6028 :                 while (*end != ' ' && *end != '\t' && *end != '\0')
     670        4698 :                         end++;
     671         665 :                 last = *end == '\0';
     672         665 :                 *end = '\0';
     673         665 :                 if (os_strcmp(start, "WPA-PSK") == 0)
     674         200 :                         val |= WPA_KEY_MGMT_PSK;
     675         465 :                 else if (os_strcmp(start, "WPA-EAP") == 0)
     676         389 :                         val |= WPA_KEY_MGMT_IEEE8021X;
     677             : #ifdef CONFIG_IEEE80211R
     678          76 :                 else if (os_strcmp(start, "FT-PSK") == 0)
     679          33 :                         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         663 :                 if (last)
     711         650 :                         break;
     712          13 :                 start = end + 1;
     713             :         }
     714             : 
     715         651 :         os_free(buf);
     716         651 :         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         650 :         return val;
     723             : }
     724             : 
     725             : 
     726         661 : static int hostapd_config_parse_cipher(int line, const char *value)
     727             : {
     728         661 :         int val = wpa_parse_cipher(value);
     729         661 :         if (val < 0) {
     730           3 :                 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
     731             :                            line, value);
     732           3 :                 return -1;
     733             :         }
     734         658 :         if (val == 0) {
     735           1 :                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
     736             :                            line);
     737           1 :                 return -1;
     738             :         }
     739         657 :         return val;
     740             : }
     741             : 
     742             : 
     743          21 : static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
     744             :                                    char *val)
     745             : {
     746          21 :         size_t len = os_strlen(val);
     747             : 
     748          21 :         if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL)
     749           0 :                 return -1;
     750             : 
     751          21 :         if (val[0] == '"') {
     752          19 :                 if (len < 2 || val[len - 1] != '"')
     753           2 :                         return -1;
     754          17 :                 len -= 2;
     755          17 :                 wep->key[keyidx] = os_malloc(len);
     756          17 :                 if (wep->key[keyidx] == NULL)
     757           0 :                         return -1;
     758          17 :                 os_memcpy(wep->key[keyidx], val + 1, len);
     759          17 :                 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          17 :         wep->keys_set++;
     773             : 
     774          17 :         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          81 : static int add_r0kh(struct hostapd_bss_config *bss, char *value)
     953             : {
     954             :         struct ft_remote_r0kh *r0kh;
     955             :         char *pos, *next;
     956             : 
     957          81 :         r0kh = os_zalloc(sizeof(*r0kh));
     958          81 :         if (r0kh == NULL)
     959           0 :                 return -1;
     960             : 
     961             :         /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
     962          81 :         pos = value;
     963          81 :         next = os_strchr(pos, ' ');
     964          81 :         if (next)
     965          81 :                 *next++ = '\0';
     966          81 :         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          80 :         pos = next;
     973          80 :         next = os_strchr(pos, ' ');
     974          80 :         if (next)
     975          80 :                 *next++ = '\0';
     976          80 :         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          79 :         r0kh->id_len = next - pos - 1;
     982          79 :         os_memcpy(r0kh->id, pos, r0kh->id_len);
     983             : 
     984          79 :         pos = next;
     985          79 :         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          78 :         r0kh->next = bss->r0kh_list;
     992          78 :         bss->r0kh_list = r0kh;
     993             : 
     994          78 :         return 0;
     995             : }
     996             : 
     997             : 
     998          42 : static int add_r1kh(struct hostapd_bss_config *bss, char *value)
     999             : {
    1000             :         struct ft_remote_r1kh *r1kh;
    1001             :         char *pos, *next;
    1002             : 
    1003          42 :         r1kh = os_zalloc(sizeof(*r1kh));
    1004          42 :         if (r1kh == NULL)
    1005           0 :                 return -1;
    1006             : 
    1007             :         /* 02:01:02:03:04:05 02:01:02:03:04:05
    1008             :          * 000102030405060708090a0b0c0d0e0f */
    1009          42 :         pos = value;
    1010          42 :         next = os_strchr(pos, ' ');
    1011          42 :         if (next)
    1012          42 :                 *next++ = '\0';
    1013          42 :         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          41 :         pos = next;
    1020          41 :         next = os_strchr(pos, ' ');
    1021          41 :         if (next)
    1022          41 :                 *next++ = '\0';
    1023          41 :         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          40 :         pos = next;
    1030          40 :         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          39 :         r1kh->next = bss->r1kh_list;
    1037          39 :         bss->r1kh_list = r1kh;
    1038             : 
    1039          39 :         return 0;
    1040             : }
    1041             : #endif /* CONFIG_IEEE80211R */
    1042             : 
    1043             : 
    1044             : #ifdef CONFIG_IEEE80211N
    1045          55 : static int hostapd_config_ht_capab(struct hostapd_config *conf,
    1046             :                                    const char *capab)
    1047             : {
    1048          55 :         if (os_strstr(capab, "[LDPC]"))
    1049           1 :                 conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
    1050          55 :         if (os_strstr(capab, "[HT40-]")) {
    1051          16 :                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
    1052          16 :                 conf->secondary_channel = -1;
    1053             :         }
    1054          55 :         if (os_strstr(capab, "[HT40+]")) {
    1055          33 :                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
    1056          33 :                 conf->secondary_channel = 1;
    1057             :         }
    1058          55 :         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          55 :         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          55 :         if (os_strstr(capab, "[GF]"))
    1067           1 :                 conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
    1068          55 :         if (os_strstr(capab, "[SHORT-GI-20]"))
    1069           1 :                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
    1070          55 :         if (os_strstr(capab, "[SHORT-GI-40]"))
    1071           3 :                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
    1072          55 :         if (os_strstr(capab, "[TX-STBC]"))
    1073           1 :                 conf->ht_capab |= HT_CAP_INFO_TX_STBC;
    1074          55 :         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          55 :         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          55 :         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          55 :         if (os_strstr(capab, "[DELAYED-BA]"))
    1087           1 :                 conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
    1088          55 :         if (os_strstr(capab, "[MAX-AMSDU-7935]"))
    1089           1 :                 conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
    1090          55 :         if (os_strstr(capab, "[DSSS_CCK-40]"))
    1091           1 :                 conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
    1092          55 :         if (os_strstr(capab, "[40-INTOLERANT]"))
    1093           2 :                 conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
    1094          55 :         if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
    1095           1 :                 conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
    1096             : 
    1097          55 :         return 0;
    1098             : }
    1099             : #endif /* CONFIG_IEEE80211N */
    1100             : 
    1101             : 
    1102             : #ifdef CONFIG_IEEE80211AC
    1103          12 : static int hostapd_config_vht_capab(struct hostapd_config *conf,
    1104             :                                     const char *capab)
    1105             : {
    1106          12 :         if (os_strstr(capab, "[MAX-MPDU-7991]"))
    1107           1 :                 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
    1108          12 :         if (os_strstr(capab, "[MAX-MPDU-11454]"))
    1109           3 :                 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
    1110          12 :         if (os_strstr(capab, "[VHT160]"))
    1111           1 :                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
    1112          12 :         if (os_strstr(capab, "[VHT160-80PLUS80]"))
    1113           1 :                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
    1114          12 :         if (os_strstr(capab, "[RXLDPC]"))
    1115           2 :                 conf->vht_capab |= VHT_CAP_RXLDPC;
    1116          12 :         if (os_strstr(capab, "[SHORT-GI-80]"))
    1117           2 :                 conf->vht_capab |= VHT_CAP_SHORT_GI_80;
    1118          12 :         if (os_strstr(capab, "[SHORT-GI-160]"))
    1119           1 :                 conf->vht_capab |= VHT_CAP_SHORT_GI_160;
    1120          12 :         if (os_strstr(capab, "[TX-STBC-2BY1]"))
    1121           2 :                 conf->vht_capab |= VHT_CAP_TXSTBC;
    1122          12 :         if (os_strstr(capab, "[RX-STBC-1]"))
    1123           2 :                 conf->vht_capab |= VHT_CAP_RXSTBC_1;
    1124          12 :         if (os_strstr(capab, "[RX-STBC-12]"))
    1125           1 :                 conf->vht_capab |= VHT_CAP_RXSTBC_2;
    1126          12 :         if (os_strstr(capab, "[RX-STBC-123]"))
    1127           1 :                 conf->vht_capab |= VHT_CAP_RXSTBC_3;
    1128          12 :         if (os_strstr(capab, "[RX-STBC-1234]"))
    1129           1 :                 conf->vht_capab |= VHT_CAP_RXSTBC_4;
    1130          12 :         if (os_strstr(capab, "[SU-BEAMFORMER]"))
    1131           1 :                 conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE;
    1132          12 :         if (os_strstr(capab, "[SU-BEAMFORMEE]"))
    1133           1 :                 conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE;
    1134          13 :         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          13 :         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          12 :         if (os_strstr(capab, "[MU-BEAMFORMER]"))
    1141           1 :                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
    1142          12 :         if (os_strstr(capab, "[MU-BEAMFORMEE]"))
    1143           1 :                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
    1144          12 :         if (os_strstr(capab, "[VHT-TXOP-PS]"))
    1145           1 :                 conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
    1146          12 :         if (os_strstr(capab, "[HTC-VHT]"))
    1147           1 :                 conf->vht_capab |= VHT_CAP_HTC_VHT;
    1148          12 :         if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]"))
    1149           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
    1150          11 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]"))
    1151           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6;
    1152          10 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]"))
    1153           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5;
    1154           9 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]"))
    1155           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4;
    1156           8 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]"))
    1157           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3;
    1158           7 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]"))
    1159           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2;
    1160           6 :         else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]"))
    1161           1 :                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1;
    1162          13 :         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          13 :         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          12 :         if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
    1169           1 :                 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
    1170          12 :         if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
    1171           1 :                 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
    1172          12 :         return 0;
    1173             : }
    1174             : #endif /* CONFIG_IEEE80211AC */
    1175             : 
    1176             : 
    1177             : #ifdef CONFIG_INTERWORKING
    1178         466 : static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
    1179             :                                     int line)
    1180             : {
    1181         466 :         size_t len = os_strlen(pos);
    1182             :         u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
    1183             : 
    1184             :         struct hostapd_roaming_consortium *rc;
    1185             : 
    1186         929 :         if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
    1187         463 :             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         463 :         len /= 2;
    1193             : 
    1194         463 :         rc = os_realloc_array(bss->roaming_consortium,
    1195         463 :                               bss->roaming_consortium_count + 1,
    1196             :                               sizeof(struct hostapd_roaming_consortium));
    1197         463 :         if (rc == NULL)
    1198           0 :                 return -1;
    1199             : 
    1200         463 :         os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
    1201         463 :         rc[bss->roaming_consortium_count].len = len;
    1202             : 
    1203         463 :         bss->roaming_consortium = rc;
    1204         463 :         bss->roaming_consortium_count++;
    1205             : 
    1206         463 :         return 0;
    1207             : }
    1208             : 
    1209             : 
    1210         294 : static int parse_lang_string(struct hostapd_lang_string **array,
    1211             :                              unsigned int *count, char *pos)
    1212             : {
    1213         294 :         char *sep, *str = NULL;
    1214             :         size_t clen, nlen, slen;
    1215             :         struct hostapd_lang_string *ls;
    1216         294 :         int ret = -1;
    1217             : 
    1218         294 :         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         293 :         sep = os_strchr(pos, ':');
    1226         293 :         if (sep == NULL)
    1227           2 :                 goto fail;
    1228         291 :         *sep++ = '\0';
    1229             : 
    1230         291 :         clen = os_strlen(pos);
    1231         291 :         if (clen < 2 || clen > sizeof(ls->lang))
    1232             :                 goto fail;
    1233         286 :         nlen = os_strlen(sep);
    1234         286 :         if (nlen > 252)
    1235           1 :                 goto fail;
    1236             : 
    1237         285 :         ls = os_realloc_array(*array, *count + 1,
    1238             :                               sizeof(struct hostapd_lang_string));
    1239         285 :         if (ls == NULL)
    1240           0 :                 goto fail;
    1241             : 
    1242         285 :         *array = ls;
    1243         285 :         ls = &(*array)[*count];
    1244         285 :         (*count)++;
    1245             : 
    1246         285 :         os_memset(ls->lang, 0, sizeof(ls->lang));
    1247         285 :         os_memcpy(ls->lang, pos, clen);
    1248         285 :         ls->name_len = nlen;
    1249         285 :         os_memcpy(ls->name, sep, nlen);
    1250             : 
    1251         285 :         ret = 0;
    1252             : fail:
    1253         293 :         os_free(str);
    1254         293 :         return ret;
    1255             : }
    1256             : 
    1257             : 
    1258         242 : static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
    1259             :                             int line)
    1260             : {
    1261         242 :         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         236 :         return 0;
    1267             : }
    1268             : 
    1269             : 
    1270         123 : 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         123 :         u8 *info = NULL, *ipos;
    1276             : 
    1277             :         /* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
    1278             : 
    1279         123 :         count = 1;
    1280        1005 :         for (pos = buf; *pos; pos++) {
    1281         883 :                 if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',')
    1282           1 :                         goto fail;
    1283         882 :                 if (*pos == ';')
    1284         133 :                         count++;
    1285             :         }
    1286         122 :         if (1 + count * 3 > 0x7f)
    1287           1 :                 goto fail;
    1288             : 
    1289         121 :         info = os_zalloc(2 + 3 + count * 3);
    1290         121 :         if (info == NULL)
    1291           0 :                 return -1;
    1292             : 
    1293         121 :         ipos = info;
    1294         121 :         *ipos++ = 0; /* GUD - Version 1 */
    1295         121 :         *ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
    1296         121 :         *ipos++ = 0; /* PLMN List IEI */
    1297             :         /* ext(b8) | Length of PLMN List value contents(b7..1) */
    1298         121 :         *ipos++ = 1 + count * 3;
    1299         121 :         *ipos++ = count; /* Number of PLMNs */
    1300             : 
    1301         121 :         pos = buf;
    1302         362 :         while (pos && *pos) {
    1303             :                 char *mcc, *mnc;
    1304             :                 size_t mnc_len;
    1305             : 
    1306         124 :                 mcc = pos;
    1307         124 :                 mnc = os_strchr(pos, ',');
    1308         124 :                 if (mnc == NULL)
    1309           1 :                         goto fail;
    1310         123 :                 *mnc++ = '\0';
    1311         123 :                 pos = os_strchr(mnc, ';');
    1312         123 :                 if (pos)
    1313           3 :                         *pos++ = '\0';
    1314             : 
    1315         123 :                 mnc_len = os_strlen(mnc);
    1316         123 :                 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         120 :                 *ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
    1322             :                 /* MNC digit 3 | MCC digit 3 */
    1323         240 :                 *ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
    1324         120 :                         (mcc[2] - '0');
    1325             :                 /* MNC digit 2 | MNC digit 1 */
    1326         120 :                 *ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
    1327             :         }
    1328             : 
    1329         117 :         os_free(bss->anqp_3gpp_cell_net);
    1330         117 :         bss->anqp_3gpp_cell_net = info;
    1331         117 :         bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
    1332         234 :         wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
    1333         117 :                     bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
    1334             : 
    1335         117 :         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         214 : 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         214 :         offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS,
    1353             :                             sizeof(int));
    1354         214 :         if (offsets == NULL)
    1355           0 :                 return -1;
    1356             : 
    1357         305 :         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         214 :         realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1,
    1367             :                                  sizeof(struct hostapd_nai_realm_data));
    1368         214 :         if (realm == NULL) {
    1369           0 :                 os_free(offsets);
    1370           0 :                 return -1;
    1371             :         }
    1372         214 :         bss->nai_realm_data = realm;
    1373             : 
    1374             :         /* patch the pointers after realloc */
    1375         305 :         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         214 :         os_free(offsets);
    1386             : 
    1387         214 :         realm = &bss->nai_realm_data[bss->nai_realm_count];
    1388         214 :         os_memset(realm, 0, sizeof(*realm));
    1389             : 
    1390         214 :         pos = buf;
    1391         214 :         realm->encoding = atoi(pos);
    1392         214 :         pos = os_strchr(pos, ',');
    1393         214 :         if (pos == NULL)
    1394           1 :                 goto fail;
    1395         213 :         pos++;
    1396             : 
    1397         213 :         end = os_strchr(pos, ',');
    1398         213 :         if (end) {
    1399         122 :                 len = end - pos;
    1400         122 :                 *end = '\0';
    1401             :         } else {
    1402          91 :                 len = os_strlen(pos);
    1403             :         }
    1404             : 
    1405         213 :         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         212 :         os_memcpy(realm->realm_buf, pos, len);
    1411             : 
    1412         212 :         if (end)
    1413         122 :                 pos = end + 1;
    1414             :         else
    1415          90 :                 pos = NULL;
    1416             : 
    1417         521 :         while (pos && *pos) {
    1418             :                 struct hostapd_nai_realm_eap *eap;
    1419             : 
    1420         219 :                 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         218 :                 eap = &realm->eap_method[realm->eap_method_count];
    1426         218 :                 realm->eap_method_count++;
    1427             : 
    1428         218 :                 end = os_strchr(pos, ',');
    1429         218 :                 if (end == NULL)
    1430         121 :                         end = pos + os_strlen(pos);
    1431             : 
    1432         218 :                 eap->eap_method = atoi(pos);
    1433             :                 for (;;) {
    1434         525 :                         pos = os_strchr(pos, '[');
    1435         525 :                         if (pos == NULL || pos > end)
    1436             :                                 break;
    1437         310 :                         pos++;
    1438         310 :                         if (eap->num_auths >= MAX_NAI_AUTH_TYPES) {
    1439           1 :                                 wpa_printf(MSG_ERROR, "Too many auth params");
    1440           1 :                                 goto fail;
    1441             :                         }
    1442         309 :                         eap->auth_id[eap->num_auths] = atoi(pos);
    1443         309 :                         pos = os_strchr(pos, ':');
    1444         309 :                         if (pos == NULL || pos > end)
    1445             :                                 goto fail;
    1446         308 :                         pos++;
    1447         308 :                         eap->auth_val[eap->num_auths] = atoi(pos);
    1448         308 :                         pos = os_strchr(pos, ']');
    1449         308 :                         if (pos == NULL || pos > end)
    1450             :                                 goto fail;
    1451         307 :                         pos++;
    1452         307 :                         eap->num_auths++;
    1453         307 :                 }
    1454             : 
    1455         215 :                 if (*end != ',')
    1456         118 :                         break;
    1457             : 
    1458          97 :                 pos = end + 1;
    1459             :         }
    1460             : 
    1461             :         /* Split realm list into null terminated realms */
    1462         208 :         rpos = realm->realm_buf;
    1463         208 :         i = 0;
    1464         428 :         while (*rpos) {
    1465         220 :                 if (i >= MAX_NAI_REALMS) {
    1466           1 :                         wpa_printf(MSG_ERROR, "Too many realms");
    1467           1 :                         goto fail;
    1468             :                 }
    1469         219 :                 realm->realm[i++] = rpos;
    1470         219 :                 rpos = os_strchr(rpos, ';');
    1471         219 :                 if (rpos == NULL)
    1472         207 :                         break;
    1473          12 :                 *rpos++ = '\0';
    1474             :         }
    1475             : 
    1476         207 :         bss->nai_realm_count++;
    1477             : 
    1478         207 :         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         358 : 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         358 :         if (bss->hs20_connection_capability_len >= 0xfff0)
    1537           0 :                 return -1;
    1538             : 
    1539         358 :         conn_cap = os_realloc(bss->hs20_connection_capability,
    1540         358 :                               bss->hs20_connection_capability_len + 4);
    1541         358 :         if (conn_cap == NULL)
    1542           0 :                 return -1;
    1543             : 
    1544         358 :         bss->hs20_connection_capability = conn_cap;
    1545         358 :         conn_cap += bss->hs20_connection_capability_len;
    1546         358 :         pos = buf;
    1547         358 :         conn_cap[0] = atoi(pos);
    1548         358 :         pos = os_strchr(pos, ':');
    1549         358 :         if (pos == NULL)
    1550           1 :                 return -1;
    1551         357 :         pos++;
    1552         357 :         WPA_PUT_LE16(conn_cap + 1, atoi(pos));
    1553         357 :         pos = os_strchr(pos, ':');
    1554         357 :         if (pos == NULL)
    1555           1 :                 return -1;
    1556         356 :         pos++;
    1557         356 :         conn_cap[3] = atoi(pos);
    1558         356 :         bss->hs20_connection_capability_len += 4;
    1559             : 
    1560         356 :         return 0;
    1561             : }
    1562             : 
    1563             : 
    1564         123 : 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         123 :         wan_metrics = os_zalloc(13);
    1573         123 :         if (wan_metrics == NULL)
    1574           0 :                 return -1;
    1575             : 
    1576         123 :         pos = buf;
    1577             :         /* WAN Info */
    1578         123 :         if (hexstr2bin(pos, wan_metrics, 1) < 0)
    1579           1 :                 goto fail;
    1580         122 :         pos += 2;
    1581         122 :         if (*pos != ':')
    1582           1 :                 goto fail;
    1583         121 :         pos++;
    1584             : 
    1585             :         /* Downlink Speed */
    1586         121 :         WPA_PUT_LE32(wan_metrics + 1, atoi(pos));
    1587         121 :         pos = os_strchr(pos, ':');
    1588         121 :         if (pos == NULL)
    1589           1 :                 goto fail;
    1590         120 :         pos++;
    1591             : 
    1592             :         /* Uplink Speed */
    1593         120 :         WPA_PUT_LE32(wan_metrics + 5, atoi(pos));
    1594         120 :         pos = os_strchr(pos, ':');
    1595         120 :         if (pos == NULL)
    1596           1 :                 goto fail;
    1597         119 :         pos++;
    1598             : 
    1599             :         /* Downlink Load */
    1600         119 :         wan_metrics[9] = atoi(pos);
    1601         119 :         pos = os_strchr(pos, ':');
    1602         119 :         if (pos == NULL)
    1603           1 :                 goto fail;
    1604         118 :         pos++;
    1605             : 
    1606             :         /* Uplink Load */
    1607         118 :         wan_metrics[10] = atoi(pos);
    1608         118 :         pos = os_strchr(pos, ':');
    1609         118 :         if (pos == NULL)
    1610           1 :                 goto fail;
    1611         117 :         pos++;
    1612             : 
    1613             :         /* LMD */
    1614         117 :         WPA_PUT_LE16(wan_metrics + 11, atoi(pos));
    1615             : 
    1616         117 :         os_free(bss->hs20_wan_metrics);
    1617         117 :         bss->hs20_wan_metrics = wan_metrics;
    1618             : 
    1619         117 :         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       16655 : static int hostapd_config_fill(struct hostapd_config *conf,
    1860             :                                struct hostapd_bss_config *bss,
    1861             :                                char *buf, char *pos, int line)
    1862             : {
    1863       16655 :         if (os_strcmp(buf, "interface") == 0) {
    1864          64 :                 os_strlcpy(conf->bss[0]->iface, pos,
    1865             :                            sizeof(conf->bss[0]->iface));
    1866       16591 :         } else if (os_strcmp(buf, "bridge") == 0) {
    1867          15 :                 os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
    1868       16576 :         } else if (os_strcmp(buf, "vlan_bridge") == 0) {
    1869           0 :                 os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
    1870       16576 :         } else if (os_strcmp(buf, "wds_bridge") == 0) {
    1871           1 :                 os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
    1872       16575 :         } else if (os_strcmp(buf, "driver") == 0) {
    1873             :                 int j;
    1874             :                 /* clear to get error below if setting is invalid */
    1875        1054 :                 conf->driver = NULL;
    1876        1064 :                 for (j = 0; wpa_drivers[j]; j++) {
    1877        1064 :                         if (os_strcmp(pos, wpa_drivers[j]->name) == 0) {
    1878        1054 :                                 conf->driver = wpa_drivers[j];
    1879        1054 :                                 break;
    1880             :                         }
    1881             :                 }
    1882        1054 :                 if (conf->driver == NULL) {
    1883           0 :                         wpa_printf(MSG_ERROR,
    1884             :                                    "Line %d: invalid/unknown driver '%s'",
    1885             :                                    line, pos);
    1886           0 :                         return 1;
    1887             :                 }
    1888       15521 :         } else if (os_strcmp(buf, "driver_params") == 0) {
    1889           2 :                 os_free(conf->driver_params);
    1890           2 :                 conf->driver_params = os_strdup(pos);
    1891       15519 :         } else if (os_strcmp(buf, "debug") == 0) {
    1892           0 :                 wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore",
    1893             :                            line);
    1894       15519 :         } else if (os_strcmp(buf, "logger_syslog_level") == 0) {
    1895           0 :                 bss->logger_syslog_level = atoi(pos);
    1896       15519 :         } else if (os_strcmp(buf, "logger_stdout_level") == 0) {
    1897         975 :                 bss->logger_stdout_level = atoi(pos);
    1898       14544 :         } else if (os_strcmp(buf, "logger_syslog") == 0) {
    1899           0 :                 bss->logger_syslog = atoi(pos);
    1900       14544 :         } else if (os_strcmp(buf, "logger_stdout") == 0) {
    1901         978 :                 bss->logger_stdout = atoi(pos);
    1902       13566 :         } else if (os_strcmp(buf, "dump_file") == 0) {
    1903           0 :                 wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
    1904             :                            line);
    1905       13566 :         } else if (os_strcmp(buf, "ssid") == 0) {
    1906        1036 :                 bss->ssid.ssid_len = os_strlen(pos);
    1907        2071 :                 if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
    1908        1035 :                     bss->ssid.ssid_len < 1) {
    1909           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
    1910             :                                    line, pos);
    1911           1 :                         return 1;
    1912             :                 }
    1913        1035 :                 os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len);
    1914        1035 :                 bss->ssid.ssid_set = 1;
    1915       12530 :         } else if (os_strcmp(buf, "ssid2") == 0) {
    1916             :                 size_t slen;
    1917           2 :                 char *str = wpa_config_parse_string(pos, &slen);
    1918           2 :                 if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
    1919           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
    1920             :                                    line, pos);
    1921           0 :                         os_free(str);
    1922           0 :                         return 1;
    1923             :                 }
    1924           2 :                 os_memcpy(bss->ssid.ssid, str, slen);
    1925           2 :                 bss->ssid.ssid_len = slen;
    1926           2 :                 bss->ssid.ssid_set = 1;
    1927           2 :                 os_free(str);
    1928       12528 :         } else if (os_strcmp(buf, "utf8_ssid") == 0) {
    1929           1 :                 bss->ssid.utf8_ssid = atoi(pos) > 0;
    1930       12527 :         } else if (os_strcmp(buf, "macaddr_acl") == 0) {
    1931           5 :                 bss->macaddr_acl = atoi(pos);
    1932          10 :                 if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
    1933           8 :                     bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
    1934           3 :                     bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
    1935           0 :                         wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d",
    1936           0 :                                    line, bss->macaddr_acl);
    1937             :                 }
    1938       12522 :         } else if (os_strcmp(buf, "accept_mac_file") == 0) {
    1939           6 :                 if (hostapd_config_read_maclist(pos, &bss->accept_mac,
    1940             :                                                 &bss->num_accept_mac)) {
    1941           0 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'",
    1942             :                                    line, pos);
    1943           0 :                         return 1;
    1944             :                 }
    1945       12516 :         } else if (os_strcmp(buf, "deny_mac_file") == 0) {
    1946           2 :                 if (hostapd_config_read_maclist(pos, &bss->deny_mac,
    1947             :                                                 &bss->num_deny_mac)) {
    1948           0 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'",
    1949             :                                    line, pos);
    1950           0 :                         return 1;
    1951             :                 }
    1952       12514 :         } else if (os_strcmp(buf, "wds_sta") == 0) {
    1953           1 :                 bss->wds_sta = atoi(pos);
    1954       12513 :         } else if (os_strcmp(buf, "start_disabled") == 0) {
    1955           0 :                 bss->start_disabled = atoi(pos);
    1956       12513 :         } else if (os_strcmp(buf, "ap_isolate") == 0) {
    1957           5 :                 bss->isolate = atoi(pos);
    1958       12508 :         } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
    1959           3 :                 bss->ap_max_inactivity = atoi(pos);
    1960       12505 :         } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
    1961           1 :                 bss->skip_inactivity_poll = atoi(pos);
    1962       12504 :         } else if (os_strcmp(buf, "country_code") == 0) {
    1963          40 :                 os_memcpy(conf->country, pos, 2);
    1964             :                 /* FIX: make this configurable */
    1965          40 :                 conf->country[2] = ' ';
    1966       12464 :         } else if (os_strcmp(buf, "ieee80211d") == 0) {
    1967          16 :                 conf->ieee80211d = atoi(pos);
    1968       12448 :         } else if (os_strcmp(buf, "ieee80211h") == 0) {
    1969          12 :                 conf->ieee80211h = atoi(pos);
    1970       12436 :         } else if (os_strcmp(buf, "ieee8021x") == 0) {
    1971         395 :                 bss->ieee802_1x = atoi(pos);
    1972       12041 :         } else if (os_strcmp(buf, "eapol_version") == 0) {
    1973           0 :                 bss->eapol_version = atoi(pos);
    1974           0 :                 if (bss->eapol_version < 1 || bss->eapol_version > 2) {
    1975           0 :                         wpa_printf(MSG_ERROR,
    1976             :                                    "Line %d: invalid EAPOL version (%d): '%s'.",
    1977             :                                    line, bss->eapol_version, pos);
    1978           0 :                         return 1;
    1979             :                 }
    1980           0 :                 wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version);
    1981             : #ifdef EAP_SERVER
    1982       12041 :         } else if (os_strcmp(buf, "eap_authenticator") == 0) {
    1983           0 :                 bss->eap_server = atoi(pos);
    1984           0 :                 wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line);
    1985       12041 :         } else if (os_strcmp(buf, "eap_server") == 0) {
    1986         142 :                 bss->eap_server = atoi(pos);
    1987       11899 :         } else if (os_strcmp(buf, "eap_user_file") == 0) {
    1988          57 :                 if (hostapd_config_read_eap_user(pos, bss))
    1989           0 :                         return 1;
    1990       11842 :         } else if (os_strcmp(buf, "ca_cert") == 0) {
    1991          47 :                 os_free(bss->ca_cert);
    1992          47 :                 bss->ca_cert = os_strdup(pos);
    1993       11795 :         } else if (os_strcmp(buf, "server_cert") == 0) {
    1994          46 :                 os_free(bss->server_cert);
    1995          46 :                 bss->server_cert = os_strdup(pos);
    1996       11749 :         } else if (os_strcmp(buf, "private_key") == 0) {
    1997          47 :                 os_free(bss->private_key);
    1998          47 :                 bss->private_key = os_strdup(pos);
    1999       11702 :         } else if (os_strcmp(buf, "private_key_passwd") == 0) {
    2000           0 :                 os_free(bss->private_key_passwd);
    2001           0 :                 bss->private_key_passwd = os_strdup(pos);
    2002       11702 :         } else if (os_strcmp(buf, "check_crl") == 0) {
    2003           0 :                 bss->check_crl = atoi(pos);
    2004       11702 :         } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
    2005          14 :                 os_free(bss->ocsp_stapling_response);
    2006          14 :                 bss->ocsp_stapling_response = os_strdup(pos);
    2007       11688 :         } else if (os_strcmp(buf, "dh_file") == 0) {
    2008          12 :                 os_free(bss->dh_file);
    2009          12 :                 bss->dh_file = os_strdup(pos);
    2010       11676 :         } else if (os_strcmp(buf, "openssl_ciphers") == 0) {
    2011           3 :                 os_free(bss->openssl_ciphers);
    2012           3 :                 bss->openssl_ciphers = os_strdup(pos);
    2013       11673 :         } else if (os_strcmp(buf, "fragment_size") == 0) {
    2014           4 :                 bss->fragment_size = atoi(pos);
    2015             : #ifdef EAP_SERVER_FAST
    2016       11669 :         } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
    2017          14 :                 os_free(bss->pac_opaque_encr_key);
    2018          14 :                 bss->pac_opaque_encr_key = os_malloc(16);
    2019          14 :                 if (bss->pac_opaque_encr_key == NULL) {
    2020           0 :                         wpa_printf(MSG_ERROR,
    2021             :                                    "Line %d: No memory for pac_opaque_encr_key",
    2022             :                                    line);
    2023           0 :                         return 1;
    2024          14 :                 } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) {
    2025           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key",
    2026             :                                    line);
    2027           1 :                         return 1;
    2028             :                 }
    2029       11655 :         } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
    2030          15 :                 size_t idlen = os_strlen(pos);
    2031          15 :                 if (idlen & 1) {
    2032           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id",
    2033             :                                    line);
    2034           1 :                         return 1;
    2035             :                 }
    2036          14 :                 os_free(bss->eap_fast_a_id);
    2037          14 :                 bss->eap_fast_a_id = os_malloc(idlen / 2);
    2038          28 :                 if (bss->eap_fast_a_id == NULL ||
    2039          14 :                     hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) {
    2040           1 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id",
    2041             :                                    line);
    2042           1 :                         os_free(bss->eap_fast_a_id);
    2043           1 :                         bss->eap_fast_a_id = NULL;
    2044           1 :                         return 1;
    2045             :                 } else {
    2046          13 :                         bss->eap_fast_a_id_len = idlen / 2;
    2047             :                 }
    2048       11640 :         } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
    2049          13 :                 os_free(bss->eap_fast_a_id_info);
    2050          13 :                 bss->eap_fast_a_id_info = os_strdup(pos);
    2051       11627 :         } else if (os_strcmp(buf, "eap_fast_prov") == 0) {
    2052           0 :                 bss->eap_fast_prov = atoi(pos);
    2053       11627 :         } else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
    2054           0 :                 bss->pac_key_lifetime = atoi(pos);
    2055       11627 :         } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
    2056           0 :                 bss->pac_key_refresh_time = atoi(pos);
    2057             : #endif /* EAP_SERVER_FAST */
    2058             : #ifdef EAP_SERVER_SIM
    2059       11627 :         } else if (os_strcmp(buf, "eap_sim_db") == 0) {
    2060          13 :                 os_free(bss->eap_sim_db);
    2061          13 :                 bss->eap_sim_db = os_strdup(pos);
    2062       11614 :         } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
    2063          11 :                 bss->eap_sim_aka_result_ind = atoi(pos);
    2064             : #endif /* EAP_SERVER_SIM */
    2065             : #ifdef EAP_SERVER_TNC
    2066       11603 :         } else if (os_strcmp(buf, "tnc") == 0) {
    2067           4 :                 bss->tnc = atoi(pos);
    2068             : #endif /* EAP_SERVER_TNC */
    2069             : #ifdef EAP_SERVER_PWD
    2070       11599 :         } else if (os_strcmp(buf, "pwd_group") == 0) {
    2071           7 :                 bss->pwd_group = atoi(pos);
    2072             : #endif /* EAP_SERVER_PWD */
    2073       11592 :         } else if (os_strcmp(buf, "eap_server_erp") == 0) {
    2074           6 :                 bss->eap_server_erp = atoi(pos);
    2075             : #endif /* EAP_SERVER */
    2076       11586 :         } else if (os_strcmp(buf, "eap_message") == 0) {
    2077             :                 char *term;
    2078           1 :                 os_free(bss->eap_req_id_text);
    2079           1 :                 bss->eap_req_id_text = os_strdup(pos);
    2080           1 :                 if (bss->eap_req_id_text == NULL) {
    2081           0 :                         wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text",
    2082             :                                    line);
    2083           0 :                         return 1;
    2084             :                 }
    2085           1 :                 bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text);
    2086           1 :                 term = os_strstr(bss->eap_req_id_text, "\\0");
    2087           1 :                 if (term) {
    2088           1 :                         *term++ = '\0';
    2089           1 :                         os_memmove(term, term + 1,
    2090             :                                    bss->eap_req_id_text_len -
    2091             :                                    (term - bss->eap_req_id_text) - 1);
    2092           1 :                         bss->eap_req_id_text_len--;
    2093             :                 }
    2094       11585 :         } else if (os_strcmp(buf, "erp_send_reauth_start") == 0) {
    2095           7 :                 bss->erp_send_reauth_start = atoi(pos);
    2096       11578 :         } else if (os_strcmp(buf, "erp_domain") == 0) {
    2097           9 :                 os_free(bss->erp_domain);
    2098           9 :                 bss->erp_domain = os_strdup(pos);
    2099       11569 :         } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
    2100           3 :                 bss->default_wep_key_len = atoi(pos);
    2101           3 :                 if (bss->default_wep_key_len > 13) {
    2102           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WEP key len %lu (= %lu bits)",
    2103             :                                    line,
    2104             :                                    (unsigned long) bss->default_wep_key_len,
    2105             :                                    (unsigned long)
    2106           1 :                                    bss->default_wep_key_len * 8);
    2107           1 :                         return 1;
    2108             :                 }
    2109       11566 :         } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
    2110           2 :                 bss->individual_wep_key_len = atoi(pos);
    2111           4 :                 if (bss->individual_wep_key_len < 0 ||
    2112           2 :                     bss->individual_wep_key_len > 13) {
    2113           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WEP key len %d (= %d bits)",
    2114             :                                    line, bss->individual_wep_key_len,
    2115           0 :                                    bss->individual_wep_key_len * 8);
    2116           0 :                         return 1;
    2117             :                 }
    2118       11564 :         } else if (os_strcmp(buf, "wep_rekey_period") == 0) {
    2119           1 :                 bss->wep_rekeying_period = atoi(pos);
    2120           1 :                 if (bss->wep_rekeying_period < 0) {
    2121           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
    2122             :                                    line, bss->wep_rekeying_period);
    2123           1 :                         return 1;
    2124             :                 }
    2125       11563 :         } else if (os_strcmp(buf, "eap_reauth_period") == 0) {
    2126           1 :                 bss->eap_reauth_period = atoi(pos);
    2127           1 :                 if (bss->eap_reauth_period < 0) {
    2128           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
    2129             :                                    line, bss->eap_reauth_period);
    2130           0 :                         return 1;
    2131             :                 }
    2132       11562 :         } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
    2133           0 :                 bss->eapol_key_index_workaround = atoi(pos);
    2134             : #ifdef CONFIG_IAPP
    2135             :         } else if (os_strcmp(buf, "iapp_interface") == 0) {
    2136             :                 bss->ieee802_11f = 1;
    2137             :                 os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
    2138             : #endif /* CONFIG_IAPP */
    2139       11562 :         } else if (os_strcmp(buf, "own_ip_addr") == 0) {
    2140           3 :                 if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
    2141           1 :                         wpa_printf(MSG_ERROR,
    2142             :                                    "Line %d: invalid IP address '%s'",
    2143             :                                    line, pos);
    2144           1 :                         return 1;
    2145             :                 }
    2146       11559 :         } else if (os_strcmp(buf, "nas_identifier") == 0) {
    2147         286 :                 os_free(bss->nas_identifier);
    2148         286 :                 bss->nas_identifier = os_strdup(pos);
    2149             : #ifndef CONFIG_NO_RADIUS
    2150       11273 :         } else if (os_strcmp(buf, "auth_server_addr") == 0) {
    2151        1095 :                 if (hostapd_config_read_radius_addr(
    2152         365 :                             &bss->radius->auth_servers,
    2153         365 :                             &bss->radius->num_auth_servers, pos, 1812,
    2154         365 :                             &bss->radius->auth_server)) {
    2155           2 :                         wpa_printf(MSG_ERROR,
    2156             :                                    "Line %d: invalid IP address '%s'",
    2157             :                                    line, pos);
    2158           2 :                         return 1;
    2159             :                 }
    2160       15086 :         } else if (bss->radius->auth_server &&
    2161        4178 :                    os_strcmp(buf, "auth_server_port") == 0) {
    2162         360 :                 bss->radius->auth_server->port = atoi(pos);
    2163       14366 :         } else if (bss->radius->auth_server &&
    2164        4178 :                    os_strcmp(buf, "auth_server_shared_secret") == 0) {
    2165         361 :                 int len = os_strlen(pos);
    2166         361 :                 if (len == 0) {
    2167             :                         /* RFC 2865, Ch. 3 */
    2168           1 :                         wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
    2169             :                                    line);
    2170           1 :                         return 1;
    2171             :                 }
    2172         360 :                 os_free(bss->radius->auth_server->shared_secret);
    2173         360 :                 bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
    2174         360 :                 bss->radius->auth_server->shared_secret_len = len;
    2175       10187 :         } else if (os_strcmp(buf, "acct_server_addr") == 0) {
    2176         189 :                 if (hostapd_config_read_radius_addr(
    2177          63 :                             &bss->radius->acct_servers,
    2178          63 :                             &bss->radius->num_acct_servers, pos, 1813,
    2179          63 :                             &bss->radius->acct_server)) {
    2180           2 :                         wpa_printf(MSG_ERROR,
    2181             :                                    "Line %d: invalid IP address '%s'",
    2182             :                                    line, pos);
    2183           2 :                         return 1;
    2184             :                 }
    2185       10343 :         } else if (bss->radius->acct_server &&
    2186         219 :                    os_strcmp(buf, "acct_server_port") == 0) {
    2187          56 :                 bss->radius->acct_server->port = atoi(pos);
    2188       10231 :         } else if (bss->radius->acct_server &&
    2189         223 :                    os_strcmp(buf, "acct_server_shared_secret") == 0) {
    2190          61 :                 int len = os_strlen(pos);
    2191          61 :                 if (len == 0) {
    2192             :                         /* RFC 2865, Ch. 3 */
    2193           1 :                         wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
    2194             :                                    line);
    2195           1 :                         return 1;
    2196             :                 }
    2197          60 :                 os_free(bss->radius->acct_server->shared_secret);
    2198          60 :                 bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
    2199          60 :                 bss->radius->acct_server->shared_secret_len = len;
    2200       10007 :         } else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
    2201           0 :                 bss->radius->retry_primary_interval = atoi(pos);
    2202       10007 :         } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
    2203           2 :                 bss->acct_interim_interval = atoi(pos);
    2204       10005 :         } else if (os_strcmp(buf, "radius_request_cui") == 0) {
    2205           1 :                 bss->radius_request_cui = atoi(pos);
    2206       10004 :         } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
    2207             :                 struct hostapd_radius_attr *attr, *a;
    2208           3 :                 attr = hostapd_parse_radius_attr(pos);
    2209           3 :                 if (attr == NULL) {
    2210           1 :                         wpa_printf(MSG_ERROR,
    2211             :                                    "Line %d: invalid radius_auth_req_attr",
    2212             :                                    line);
    2213           1 :                         return 1;
    2214           2 :                 } else if (bss->radius_auth_req_attr == NULL) {
    2215           1 :                         bss->radius_auth_req_attr = attr;
    2216             :                 } else {
    2217           1 :                         a = bss->radius_auth_req_attr;
    2218           2 :                         while (a->next)
    2219           0 :                                 a = a->next;
    2220           1 :                         a->next = attr;
    2221             :                 }
    2222       10001 :         } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
    2223             :                 struct hostapd_radius_attr *attr, *a;
    2224           3 :                 attr = hostapd_parse_radius_attr(pos);
    2225           3 :                 if (attr == NULL) {
    2226           1 :                         wpa_printf(MSG_ERROR,
    2227             :                                    "Line %d: invalid radius_acct_req_attr",
    2228             :                                    line);
    2229           1 :                         return 1;
    2230           2 :                 } else if (bss->radius_acct_req_attr == NULL) {
    2231           1 :                         bss->radius_acct_req_attr = attr;
    2232             :                 } else {
    2233           1 :                         a = bss->radius_acct_req_attr;
    2234           2 :                         while (a->next)
    2235           0 :                                 a = a->next;
    2236           1 :                         a->next = attr;
    2237             :                 }
    2238        9998 :         } else if (os_strcmp(buf, "radius_das_port") == 0) {
    2239           2 :                 bss->radius_das_port = atoi(pos);
    2240        9996 :         } else if (os_strcmp(buf, "radius_das_client") == 0) {
    2241           4 :                 if (hostapd_parse_das_client(bss, pos) < 0) {
    2242           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid DAS client",
    2243             :                                    line);
    2244           2 :                         return 1;
    2245             :                 }
    2246        9992 :         } else if (os_strcmp(buf, "radius_das_time_window") == 0) {
    2247           0 :                 bss->radius_das_time_window = atoi(pos);
    2248        9992 :         } else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
    2249           2 :                 bss->radius_das_require_event_timestamp = atoi(pos);
    2250             : #endif /* CONFIG_NO_RADIUS */
    2251        9990 :         } else if (os_strcmp(buf, "auth_algs") == 0) {
    2252           9 :                 bss->auth_algs = atoi(pos);
    2253           9 :                 if (bss->auth_algs == 0) {
    2254           1 :                         wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed",
    2255             :                                    line);
    2256           1 :                         return 1;
    2257             :                 }
    2258        9981 :         } else if (os_strcmp(buf, "max_num_sta") == 0) {
    2259           3 :                 bss->max_num_sta = atoi(pos);
    2260           5 :                 if (bss->max_num_sta < 0 ||
    2261           2 :                     bss->max_num_sta > MAX_STA_COUNT) {
    2262           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
    2263             :                                    line, bss->max_num_sta, MAX_STA_COUNT);
    2264           2 :                         return 1;
    2265             :                 }
    2266        9978 :         } else if (os_strcmp(buf, "wpa") == 0) {
    2267         648 :                 bss->wpa = atoi(pos);
    2268        9330 :         } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
    2269           5 :                 bss->wpa_group_rekey = atoi(pos);
    2270        9325 :         } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
    2271           1 :                 bss->wpa_strict_rekey = atoi(pos);
    2272        9324 :         } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
    2273           1 :                 bss->wpa_gmk_rekey = atoi(pos);
    2274        9323 :         } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
    2275           3 :                 bss->wpa_ptk_rekey = atoi(pos);
    2276        9320 :         } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
    2277         246 :                 int len = os_strlen(pos);
    2278         246 :                 if (len < 8 || len > 63) {
    2279           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)",
    2280             :                                    line, len);
    2281           2 :                         return 1;
    2282             :                 }
    2283         244 :                 os_free(bss->ssid.wpa_passphrase);
    2284         244 :                 bss->ssid.wpa_passphrase = os_strdup(pos);
    2285         244 :                 if (bss->ssid.wpa_passphrase) {
    2286         243 :                         os_free(bss->ssid.wpa_psk);
    2287         243 :                         bss->ssid.wpa_psk = NULL;
    2288         243 :                         bss->ssid.wpa_passphrase_set = 1;
    2289             :                 }
    2290        9074 :         } else if (os_strcmp(buf, "wpa_psk") == 0) {
    2291          13 :                 os_free(bss->ssid.wpa_psk);
    2292          13 :                 bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
    2293          13 :                 if (bss->ssid.wpa_psk == NULL)
    2294           0 :                         return 1;
    2295          25 :                 if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) ||
    2296          12 :                     pos[PMK_LEN * 2] != '\0') {
    2297           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
    2298             :                                    line, pos);
    2299           2 :                         os_free(bss->ssid.wpa_psk);
    2300           2 :                         bss->ssid.wpa_psk = NULL;
    2301           2 :                         return 1;
    2302             :                 }
    2303          11 :                 bss->ssid.wpa_psk->group = 1;
    2304          11 :                 os_free(bss->ssid.wpa_passphrase);
    2305          11 :                 bss->ssid.wpa_passphrase = NULL;
    2306          11 :                 bss->ssid.wpa_psk_set = 1;
    2307        9061 :         } else if (os_strcmp(buf, "wpa_psk_file") == 0) {
    2308          22 :                 os_free(bss->ssid.wpa_psk_file);
    2309          22 :                 bss->ssid.wpa_psk_file = os_strdup(pos);
    2310          22 :                 if (!bss->ssid.wpa_psk_file) {
    2311           1 :                         wpa_printf(MSG_ERROR, "Line %d: allocation failed",
    2312             :                                    line);
    2313           1 :                         return 1;
    2314             :                 }
    2315        9039 :         } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
    2316         657 :                 bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
    2317         657 :                 if (bss->wpa_key_mgmt == -1)
    2318           7 :                         return 1;
    2319        8382 :         } else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
    2320           3 :                 bss->wpa_psk_radius = atoi(pos);
    2321           6 :                 if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
    2322           5 :                     bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
    2323           2 :                     bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
    2324           1 :                         wpa_printf(MSG_ERROR,
    2325             :                                    "Line %d: unknown wpa_psk_radius %d",
    2326           1 :                                    line, bss->wpa_psk_radius);
    2327           1 :                         return 1;
    2328             :                 }
    2329        8379 :         } else if (os_strcmp(buf, "wpa_pairwise") == 0) {
    2330          23 :                 bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos);
    2331          23 :                 if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0)
    2332           2 :                         return 1;
    2333          21 :                 if (bss->wpa_pairwise &
    2334             :                     (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
    2335           3 :                         wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
    2336             :                                    bss->wpa_pairwise, pos);
    2337           3 :                         return 1;
    2338             :                 }
    2339        8356 :         } else if (os_strcmp(buf, "rsn_pairwise") == 0) {
    2340         638 :                 bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos);
    2341         638 :                 if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0)
    2342           2 :                         return 1;
    2343         636 :                 if (bss->rsn_pairwise &
    2344             :                     (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
    2345           3 :                         wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
    2346             :                                    bss->rsn_pairwise, pos);
    2347           3 :                         return 1;
    2348             :                 }
    2349             : #ifdef CONFIG_RSN_PREAUTH
    2350        7718 :         } else if (os_strcmp(buf, "rsn_preauth") == 0) {
    2351           2 :                 bss->rsn_preauth = atoi(pos);
    2352        7716 :         } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
    2353           2 :                 os_free(bss->rsn_preauth_interfaces);
    2354           2 :                 bss->rsn_preauth_interfaces = os_strdup(pos);
    2355             : #endif /* CONFIG_RSN_PREAUTH */
    2356             : #ifdef CONFIG_PEERKEY
    2357        7714 :         } else if (os_strcmp(buf, "peerkey") == 0) {
    2358           3 :                 bss->peerkey = atoi(pos);
    2359             : #endif /* CONFIG_PEERKEY */
    2360             : #ifdef CONFIG_IEEE80211R
    2361        7711 :         } else if (os_strcmp(buf, "mobility_domain") == 0) {
    2362          81 :                 if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
    2363          40 :                     hexstr2bin(pos, bss->mobility_domain,
    2364             :                                MOBILITY_DOMAIN_ID_LEN) != 0) {
    2365           1 :                         wpa_printf(MSG_ERROR,
    2366             :                                    "Line %d: Invalid mobility_domain '%s'",
    2367             :                                    line, pos);
    2368           1 :                         return 1;
    2369             :                 }
    2370        7670 :         } else if (os_strcmp(buf, "r1_key_holder") == 0) {
    2371          81 :                 if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
    2372          40 :                     hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) {
    2373           1 :                         wpa_printf(MSG_ERROR,
    2374             :                                    "Line %d: Invalid r1_key_holder '%s'",
    2375             :                                    line, pos);
    2376           1 :                         return 1;
    2377             :                 }
    2378        7629 :         } else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
    2379          39 :                 bss->r0_key_lifetime = atoi(pos);
    2380        7590 :         } else if (os_strcmp(buf, "reassociation_deadline") == 0) {
    2381          40 :                 bss->reassociation_deadline = atoi(pos);
    2382        7550 :         } else if (os_strcmp(buf, "r0kh") == 0) {
    2383          81 :                 if (add_r0kh(bss, pos) < 0) {
    2384           3 :                         wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'",
    2385             :                                    line, pos);
    2386           3 :                         return 1;
    2387             :                 }
    2388        7469 :         } else if (os_strcmp(buf, "r1kh") == 0) {
    2389          42 :                 if (add_r1kh(bss, pos) < 0) {
    2390           3 :                         wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'",
    2391             :                                    line, pos);
    2392           3 :                         return 1;
    2393             :                 }
    2394        7427 :         } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
    2395          39 :                 bss->pmk_r1_push = atoi(pos);
    2396        7388 :         } else if (os_strcmp(buf, "ft_over_ds") == 0) {
    2397           0 :                 bss->ft_over_ds = atoi(pos);
    2398             : #endif /* CONFIG_IEEE80211R */
    2399             : #ifndef CONFIG_NO_CTRL_IFACE
    2400        7388 :         } else if (os_strcmp(buf, "ctrl_interface") == 0) {
    2401          70 :                 os_free(bss->ctrl_interface);
    2402          70 :                 bss->ctrl_interface = os_strdup(pos);
    2403        7318 :         } else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
    2404             : #ifndef CONFIG_NATIVE_WINDOWS
    2405             :                 struct group *grp;
    2406             :                 char *endp;
    2407          11 :                 const char *group = pos;
    2408             : 
    2409          11 :                 grp = getgrnam(group);
    2410          11 :                 if (grp) {
    2411          10 :                         bss->ctrl_interface_gid = grp->gr_gid;
    2412          10 :                         bss->ctrl_interface_gid_set = 1;
    2413          10 :                         wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')",
    2414             :                                    bss->ctrl_interface_gid, group);
    2415          21 :                         return 0;
    2416             :                 }
    2417             : 
    2418             :                 /* Group name not found - try to parse this as gid */
    2419           1 :                 bss->ctrl_interface_gid = strtol(group, &endp, 10);
    2420           1 :                 if (*group == '\0' || *endp != '\0') {
    2421           1 :                         wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'",
    2422             :                                    line, group);
    2423           1 :                         return 1;
    2424             :                 }
    2425           0 :                 bss->ctrl_interface_gid_set = 1;
    2426           0 :                 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
    2427             :                            bss->ctrl_interface_gid);
    2428             : #endif /* CONFIG_NATIVE_WINDOWS */
    2429             : #endif /* CONFIG_NO_CTRL_IFACE */
    2430             : #ifdef RADIUS_SERVER
    2431        7307 :         } else if (os_strcmp(buf, "radius_server_clients") == 0) {
    2432          15 :                 os_free(bss->radius_server_clients);
    2433          15 :                 bss->radius_server_clients = os_strdup(pos);
    2434        7292 :         } else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
    2435          10 :                 bss->radius_server_auth_port = atoi(pos);
    2436        7282 :         } else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
    2437           6 :                 bss->radius_server_acct_port = atoi(pos);
    2438        7276 :         } else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
    2439           1 :                 bss->radius_server_ipv6 = atoi(pos);
    2440             : #endif /* RADIUS_SERVER */
    2441        7275 :         } else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
    2442           0 :                 bss->use_pae_group_addr = atoi(pos);
    2443        7275 :         } else if (os_strcmp(buf, "hw_mode") == 0) {
    2444        1094 :                 if (os_strcmp(pos, "a") == 0)
    2445          40 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
    2446        1054 :                 else if (os_strcmp(pos, "b") == 0)
    2447           3 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
    2448        1051 :                 else if (os_strcmp(pos, "g") == 0)
    2449        1050 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
    2450           1 :                 else if (os_strcmp(pos, "ad") == 0)
    2451           0 :                         conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
    2452             :                 else {
    2453           1 :                         wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
    2454             :                                    line, pos);
    2455           1 :                         return 1;
    2456             :                 }
    2457        6181 :         } else if (os_strcmp(buf, "wps_rf_bands") == 0) {
    2458           1 :                 if (os_strcmp(pos, "a") == 0)
    2459           0 :                         bss->wps_rf_bands = WPS_RF_50GHZ;
    2460           2 :                 else if (os_strcmp(pos, "g") == 0 ||
    2461           1 :                          os_strcmp(pos, "b") == 0)
    2462           0 :                         bss->wps_rf_bands = WPS_RF_24GHZ;
    2463           2 :                 else if (os_strcmp(pos, "ag") == 0 ||
    2464           1 :                          os_strcmp(pos, "ga") == 0)
    2465           0 :                         bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
    2466             :                 else {
    2467           1 :                         wpa_printf(MSG_ERROR,
    2468             :                                    "Line %d: unknown wps_rf_band '%s'",
    2469             :                                    line, pos);
    2470           1 :                         return 1;
    2471             :                 }
    2472        6180 :         } else if (os_strcmp(buf, "channel") == 0) {
    2473        1149 :                 if (os_strcmp(pos, "acs_survey") == 0) {
    2474             : #ifndef CONFIG_ACS
    2475             :                         wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled",
    2476             :                                    line);
    2477             :                         return 1;
    2478             : #else /* CONFIG_ACS */
    2479           0 :                         conf->channel = 0;
    2480             : #endif /* CONFIG_ACS */
    2481             :                 } else
    2482        1149 :                         conf->channel = atoi(pos);
    2483        5031 :         } else if (os_strcmp(buf, "chanlist") == 0) {
    2484           5 :                 if (hostapd_parse_intlist(&conf->chanlist, pos)) {
    2485           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
    2486             :                                    line);
    2487           0 :                         return 1;
    2488             :                 }
    2489        5026 :         } else if (os_strcmp(buf, "beacon_int") == 0) {
    2490          16 :                 int val = atoi(pos);
    2491             :                 /* MIB defines range as 1..65535, but very small values
    2492             :                  * cause problems with the current implementation.
    2493             :                  * Since it is unlikely that this small numbers are
    2494             :                  * useful in real life scenarios, do not allow beacon
    2495             :                  * period to be set below 15 TU. */
    2496          16 :                 if (val < 15 || val > 65535) {
    2497           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid beacon_int %d (expected 15..65535)",
    2498             :                                    line, val);
    2499           2 :                         return 1;
    2500             :                 }
    2501          14 :                 conf->beacon_int = val;
    2502             : #ifdef CONFIG_ACS
    2503        5010 :         } else if (os_strcmp(buf, "acs_num_scans") == 0) {
    2504           2 :                 int val = atoi(pos);
    2505           2 :                 if (val <= 0 || val > 100) {
    2506           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)",
    2507             :                                    line, val);
    2508           2 :                         return 1;
    2509             :                 }
    2510           0 :                 conf->acs_num_scans = val;
    2511             : #endif /* CONFIG_ACS */
    2512        5008 :         } else if (os_strcmp(buf, "dtim_period") == 0) {
    2513           0 :                 bss->dtim_period = atoi(pos);
    2514           0 :                 if (bss->dtim_period < 1 || bss->dtim_period > 255) {
    2515           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d",
    2516             :                                    line, bss->dtim_period);
    2517           0 :                         return 1;
    2518             :                 }
    2519        5008 :         } else if (os_strcmp(buf, "bss_load_update_period") == 0) {
    2520           1 :                 bss->bss_load_update_period = atoi(pos);
    2521           2 :                 if (bss->bss_load_update_period < 0 ||
    2522           1 :                     bss->bss_load_update_period > 100) {
    2523           0 :                         wpa_printf(MSG_ERROR,
    2524             :                                    "Line %d: invalid bss_load_update_period %d",
    2525             :                                    line, bss->bss_load_update_period);
    2526           0 :                         return 1;
    2527             :                 }
    2528        5007 :         } else if (os_strcmp(buf, "rts_threshold") == 0) {
    2529           3 :                 conf->rts_threshold = atoi(pos);
    2530           3 :                 if (conf->rts_threshold < 0 || conf->rts_threshold > 2347) {
    2531           2 :                         wpa_printf(MSG_ERROR,
    2532             :                                    "Line %d: invalid rts_threshold %d",
    2533             :                                    line, conf->rts_threshold);
    2534           2 :                         return 1;
    2535             :                 }
    2536        5004 :         } else if (os_strcmp(buf, "fragm_threshold") == 0) {
    2537           5 :                 conf->fragm_threshold = atoi(pos);
    2538           9 :                 if (conf->fragm_threshold < 256 ||
    2539           4 :                     conf->fragm_threshold > 2346) {
    2540           2 :                         wpa_printf(MSG_ERROR,
    2541             :                                    "Line %d: invalid fragm_threshold %d",
    2542             :                                    line, conf->fragm_threshold);
    2543           2 :                         return 1;
    2544             :                 }
    2545        4999 :         } else if (os_strcmp(buf, "send_probe_response") == 0) {
    2546           2 :                 int val = atoi(pos);
    2547           2 :                 if (val != 0 && val != 1) {
    2548           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)",
    2549             :                                    line, val);
    2550           2 :                         return 1;
    2551             :                 }
    2552           0 :                 conf->send_probe_response = val;
    2553        4997 :         } else if (os_strcmp(buf, "supported_rates") == 0) {
    2554           2 :                 if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
    2555           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
    2556             :                                    line);
    2557           0 :                         return 1;
    2558             :                 }
    2559        4995 :         } else if (os_strcmp(buf, "basic_rates") == 0) {
    2560           1 :                 if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
    2561           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
    2562             :                                    line);
    2563           0 :                         return 1;
    2564             :                 }
    2565        4994 :         } else if (os_strcmp(buf, "preamble") == 0) {
    2566           1 :                 if (atoi(pos))
    2567           1 :                         conf->preamble = SHORT_PREAMBLE;
    2568             :                 else
    2569           0 :                         conf->preamble = LONG_PREAMBLE;
    2570        4993 :         } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
    2571           9 :                 bss->ignore_broadcast_ssid = atoi(pos);
    2572        4984 :         } else if (os_strcmp(buf, "wep_default_key") == 0) {
    2573           1 :                 bss->ssid.wep.idx = atoi(pos);
    2574           1 :                 if (bss->ssid.wep.idx > 3) {
    2575           1 :                         wpa_printf(MSG_ERROR,
    2576             :                                    "Invalid wep_default_key index %d",
    2577           1 :                                    bss->ssid.wep.idx);
    2578           1 :                         return 1;
    2579             :                 }
    2580        9947 :         } else if (os_strcmp(buf, "wep_key0") == 0 ||
    2581        9926 :                    os_strcmp(buf, "wep_key1") == 0 ||
    2582        9924 :                    os_strcmp(buf, "wep_key2") == 0 ||
    2583        4962 :                    os_strcmp(buf, "wep_key3") == 0) {
    2584          38 :                 if (hostapd_config_read_wep(&bss->ssid.wep,
    2585          21 :                                             buf[7] - '0', pos)) {
    2586           4 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'",
    2587             :                                    line, buf);
    2588           4 :                         return 1;
    2589             :                 }
    2590             : #ifndef CONFIG_NO_VLAN
    2591        4962 :         } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
    2592           7 :                 bss->ssid.dynamic_vlan = atoi(pos);
    2593        4955 :         } else if (os_strcmp(buf, "vlan_file") == 0) {
    2594           1 :                 if (hostapd_config_read_vlan_file(bss, pos)) {
    2595           0 :                         wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
    2596             :                                    line, pos);
    2597           0 :                         return 1;
    2598             :                 }
    2599        4954 :         } else if (os_strcmp(buf, "vlan_naming") == 0) {
    2600           2 :                 bss->ssid.vlan_naming = atoi(pos);
    2601           3 :                 if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
    2602           1 :                     bss->ssid.vlan_naming < 0) {
    2603           2 :                         wpa_printf(MSG_ERROR,
    2604             :                                    "Line %d: invalid naming scheme %d",
    2605             :                                    line, bss->ssid.vlan_naming);
    2606           2 :                         return 1;
    2607             :                 }
    2608             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
    2609        4952 :         } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
    2610           1 :                 os_free(bss->ssid.vlan_tagged_interface);
    2611           1 :                 bss->ssid.vlan_tagged_interface = os_strdup(pos);
    2612             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    2613             : #endif /* CONFIG_NO_VLAN */
    2614        4951 :         } else if (os_strcmp(buf, "ap_table_max_size") == 0) {
    2615           3 :                 conf->ap_table_max_size = atoi(pos);
    2616        4948 :         } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
    2617           1 :                 conf->ap_table_expiration_time = atoi(pos);
    2618        4947 :         } else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
    2619          13 :                 if (hostapd_config_tx_queue(conf, buf, pos)) {
    2620           5 :                         wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
    2621             :                                    line);
    2622           5 :                         return 1;
    2623             :                 }
    2624        9868 :         } else if (os_strcmp(buf, "wme_enabled") == 0 ||
    2625        4934 :                    os_strcmp(buf, "wmm_enabled") == 0) {
    2626           8 :                 bss->wmm_enabled = atoi(pos);
    2627        4926 :         } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
    2628           0 :                 bss->wmm_uapsd = atoi(pos);
    2629        9852 :         } else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
    2630        4926 :                    os_strncmp(buf, "wmm_ac_", 7) == 0) {
    2631          72 :                 if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) {
    2632          12 :                         wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item",
    2633             :                                    line);
    2634          12 :                         return 1;
    2635             :                 }
    2636        4884 :         } else if (os_strcmp(buf, "bss") == 0) {
    2637          10 :                 if (hostapd_config_bss(conf, pos)) {
    2638           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid bss item",
    2639             :                                    line);
    2640           0 :                         return 1;
    2641             :                 }
    2642        4874 :         } else if (os_strcmp(buf, "bssid") == 0) {
    2643          89 :                 if (hwaddr_aton(pos, bss->bssid)) {
    2644           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid bssid item",
    2645             :                                    line);
    2646           0 :                         return 1;
    2647             :                 }
    2648             : #ifdef CONFIG_IEEE80211W
    2649        4785 :         } else if (os_strcmp(buf, "ieee80211w") == 0) {
    2650         144 :                 bss->ieee80211w = atoi(pos);
    2651        4641 :         } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
    2652           7 :                 if (os_strcmp(pos, "AES-128-CMAC") == 0) {
    2653           1 :                         bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
    2654           6 :                 } else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
    2655           2 :                         bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
    2656           4 :                 } else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
    2657           2 :                         bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
    2658           2 :                 } else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
    2659           1 :                         bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
    2660             :                 } else {
    2661           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
    2662             :                                    line, pos);
    2663           1 :                         return 1;
    2664             :                 }
    2665        4634 :         } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
    2666           1 :                 bss->assoc_sa_query_max_timeout = atoi(pos);
    2667           1 :                 if (bss->assoc_sa_query_max_timeout == 0) {
    2668           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout",
    2669             :                                    line);
    2670           1 :                         return 1;
    2671             :                 }
    2672        4633 :         } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) {
    2673           1 :                 bss->assoc_sa_query_retry_timeout = atoi(pos);
    2674           1 :                 if (bss->assoc_sa_query_retry_timeout == 0) {
    2675           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout",
    2676             :                                    line);
    2677           1 :                         return 1;
    2678             :                 }
    2679             : #endif /* CONFIG_IEEE80211W */
    2680             : #ifdef CONFIG_IEEE80211N
    2681        4632 :         } else if (os_strcmp(buf, "ieee80211n") == 0) {
    2682        1054 :                 conf->ieee80211n = atoi(pos);
    2683        3578 :         } else if (os_strcmp(buf, "ht_capab") == 0) {
    2684          55 :                 if (hostapd_config_ht_capab(conf, pos) < 0) {
    2685           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab",
    2686             :                                    line);
    2687           0 :                         return 1;
    2688             :                 }
    2689        3523 :         } else if (os_strcmp(buf, "require_ht") == 0) {
    2690           3 :                 conf->require_ht = atoi(pos);
    2691        3520 :         } else if (os_strcmp(buf, "obss_interval") == 0) {
    2692           5 :                 conf->obss_interval = atoi(pos);
    2693             : #endif /* CONFIG_IEEE80211N */
    2694             : #ifdef CONFIG_IEEE80211AC
    2695        3515 :         } else if (os_strcmp(buf, "ieee80211ac") == 0) {
    2696          14 :                 conf->ieee80211ac = atoi(pos);
    2697        3501 :         } else if (os_strcmp(buf, "vht_capab") == 0) {
    2698          12 :                 if (hostapd_config_vht_capab(conf, pos) < 0) {
    2699           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab",
    2700             :                                    line);
    2701           0 :                         return 1;
    2702             :                 }
    2703        3489 :         } else if (os_strcmp(buf, "require_vht") == 0) {
    2704           3 :                 conf->require_vht = atoi(pos);
    2705        3486 :         } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
    2706          15 :                 conf->vht_oper_chwidth = atoi(pos);
    2707        3471 :         } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
    2708          14 :                 conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
    2709        3457 :         } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) {
    2710           2 :                 conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
    2711        3455 :         } else if (os_strcmp(buf, "vendor_vht") == 0) {
    2712           1 :                 bss->vendor_vht = atoi(pos);
    2713             : #endif /* CONFIG_IEEE80211AC */
    2714        3454 :         } else if (os_strcmp(buf, "max_listen_interval") == 0) {
    2715           1 :                 bss->max_listen_interval = atoi(pos);
    2716        3453 :         } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
    2717           8 :                 bss->disable_pmksa_caching = atoi(pos);
    2718        3445 :         } else if (os_strcmp(buf, "okc") == 0) {
    2719           6 :                 bss->okc = atoi(pos);
    2720             : #ifdef CONFIG_WPS
    2721        3439 :         } else if (os_strcmp(buf, "wps_state") == 0) {
    2722          88 :                 bss->wps_state = atoi(pos);
    2723          88 :                 if (bss->wps_state < 0 || bss->wps_state > 2) {
    2724           2 :                         wpa_printf(MSG_ERROR, "Line %d: invalid wps_state",
    2725             :                                    line);
    2726           2 :                         return 1;
    2727             :                 }
    2728        3351 :         } else if (os_strcmp(buf, "wps_independent") == 0) {
    2729           2 :                 bss->wps_independent = atoi(pos);
    2730        3349 :         } else if (os_strcmp(buf, "ap_setup_locked") == 0) {
    2731           0 :                 bss->ap_setup_locked = atoi(pos);
    2732        3349 :         } else if (os_strcmp(buf, "uuid") == 0) {
    2733          17 :                 if (uuid_str2bin(pos, bss->uuid)) {
    2734           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
    2735           1 :                         return 1;
    2736             :                 }
    2737        3332 :         } else if (os_strcmp(buf, "wps_pin_requests") == 0) {
    2738           1 :                 os_free(bss->wps_pin_requests);
    2739           1 :                 bss->wps_pin_requests = os_strdup(pos);
    2740        3331 :         } else if (os_strcmp(buf, "device_name") == 0) {
    2741          18 :                 if (os_strlen(pos) > 32) {
    2742           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long "
    2743             :                                    "device_name", line);
    2744           1 :                         return 1;
    2745             :                 }
    2746          17 :                 os_free(bss->device_name);
    2747          17 :                 bss->device_name = os_strdup(pos);
    2748        3313 :         } else if (os_strcmp(buf, "manufacturer") == 0) {
    2749          18 :                 if (os_strlen(pos) > 64) {
    2750           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer",
    2751             :                                    line);
    2752           1 :                         return 1;
    2753             :                 }
    2754          17 :                 os_free(bss->manufacturer);
    2755          17 :                 bss->manufacturer = os_strdup(pos);
    2756        3295 :         } else if (os_strcmp(buf, "model_name") == 0) {
    2757          18 :                 if (os_strlen(pos) > 32) {
    2758           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long model_name",
    2759             :                                    line);
    2760           1 :                         return 1;
    2761             :                 }
    2762          17 :                 os_free(bss->model_name);
    2763          17 :                 bss->model_name = os_strdup(pos);
    2764        3277 :         } else if (os_strcmp(buf, "model_number") == 0) {
    2765          18 :                 if (os_strlen(pos) > 32) {
    2766           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long model_number",
    2767             :                                    line);
    2768           1 :                         return 1;
    2769             :                 }
    2770          17 :                 os_free(bss->model_number);
    2771          17 :                 bss->model_number = os_strdup(pos);
    2772        3259 :         } else if (os_strcmp(buf, "serial_number") == 0) {
    2773          18 :                 if (os_strlen(pos) > 32) {
    2774           1 :                         wpa_printf(MSG_ERROR, "Line %d: Too long serial_number",
    2775             :                                    line);
    2776           1 :                         return 1;
    2777             :                 }
    2778          17 :                 os_free(bss->serial_number);
    2779          17 :                 bss->serial_number = os_strdup(pos);
    2780        3241 :         } else if (os_strcmp(buf, "device_type") == 0) {
    2781          17 :                 if (wps_dev_type_str2bin(pos, bss->device_type))
    2782           1 :                         return 1;
    2783        3224 :         } else if (os_strcmp(buf, "config_methods") == 0) {
    2784          16 :                 os_free(bss->config_methods);
    2785          16 :                 bss->config_methods = os_strdup(pos);
    2786        3208 :         } else if (os_strcmp(buf, "os_version") == 0) {
    2787          17 :                 if (hexstr2bin(pos, bss->os_version, 4)) {
    2788           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid os_version",
    2789             :                                    line);
    2790           1 :                         return 1;
    2791             :                 }
    2792        3191 :         } else if (os_strcmp(buf, "ap_pin") == 0) {
    2793          34 :                 os_free(bss->ap_pin);
    2794          34 :                 bss->ap_pin = os_strdup(pos);
    2795        3157 :         } else if (os_strcmp(buf, "skip_cred_build") == 0) {
    2796           2 :                 bss->skip_cred_build = atoi(pos);
    2797        3155 :         } else if (os_strcmp(buf, "extra_cred") == 0) {
    2798           2 :                 os_free(bss->extra_cred);
    2799           2 :                 bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len);
    2800           2 :                 if (bss->extra_cred == NULL) {
    2801           0 :                         wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'",
    2802             :                                    line, pos);
    2803           0 :                         return 1;
    2804             :                 }
    2805        3153 :         } else if (os_strcmp(buf, "wps_cred_processing") == 0) {
    2806           2 :                 bss->wps_cred_processing = atoi(pos);
    2807        3151 :         } else if (os_strcmp(buf, "ap_settings") == 0) {
    2808           1 :                 os_free(bss->ap_settings);
    2809           1 :                 bss->ap_settings =
    2810           1 :                         (u8 *) os_readfile(pos, &bss->ap_settings_len);
    2811           1 :                 if (bss->ap_settings == NULL) {
    2812           1 :                         wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'",
    2813             :                                    line, pos);
    2814           1 :                         return 1;
    2815             :                 }
    2816        3150 :         } else if (os_strcmp(buf, "upnp_iface") == 0) {
    2817          16 :                 os_free(bss->upnp_iface);
    2818          16 :                 bss->upnp_iface = os_strdup(pos);
    2819        3134 :         } else if (os_strcmp(buf, "friendly_name") == 0) {
    2820           5 :                 os_free(bss->friendly_name);
    2821           5 :                 bss->friendly_name = os_strdup(pos);
    2822        3129 :         } else if (os_strcmp(buf, "manufacturer_url") == 0) {
    2823           5 :                 os_free(bss->manufacturer_url);
    2824           5 :                 bss->manufacturer_url = os_strdup(pos);
    2825        3124 :         } else if (os_strcmp(buf, "model_description") == 0) {
    2826           5 :                 os_free(bss->model_description);
    2827           5 :                 bss->model_description = os_strdup(pos);
    2828        3119 :         } else if (os_strcmp(buf, "model_url") == 0) {
    2829           5 :                 os_free(bss->model_url);
    2830           5 :                 bss->model_url = os_strdup(pos);
    2831        3114 :         } else if (os_strcmp(buf, "upc") == 0) {
    2832           5 :                 os_free(bss->upc);
    2833           5 :                 bss->upc = os_strdup(pos);
    2834        3109 :         } else if (os_strcmp(buf, "pbc_in_m1") == 0) {
    2835           0 :                 bss->pbc_in_m1 = atoi(pos);
    2836        3109 :         } else if (os_strcmp(buf, "server_id") == 0) {
    2837          10 :                 os_free(bss->server_id);
    2838          10 :                 bss->server_id = os_strdup(pos);
    2839             : #ifdef CONFIG_WPS_NFC
    2840        3099 :         } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
    2841           2 :                 bss->wps_nfc_dev_pw_id = atoi(pos);
    2842           3 :                 if (bss->wps_nfc_dev_pw_id < 0x10 ||
    2843           1 :                     bss->wps_nfc_dev_pw_id > 0xffff) {
    2844           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value",
    2845             :                                    line);
    2846           2 :                         return 1;
    2847             :                 }
    2848           0 :                 bss->wps_nfc_pw_from_config = 1;
    2849        3097 :         } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
    2850           1 :                 wpabuf_free(bss->wps_nfc_dh_pubkey);
    2851           1 :                 bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos);
    2852           1 :                 bss->wps_nfc_pw_from_config = 1;
    2853        3096 :         } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
    2854           1 :                 wpabuf_free(bss->wps_nfc_dh_privkey);
    2855           1 :                 bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos);
    2856           1 :                 bss->wps_nfc_pw_from_config = 1;
    2857        3095 :         } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
    2858           1 :                 wpabuf_free(bss->wps_nfc_dev_pw);
    2859           1 :                 bss->wps_nfc_dev_pw = hostapd_parse_bin(pos);
    2860           1 :                 bss->wps_nfc_pw_from_config = 1;
    2861             : #endif /* CONFIG_WPS_NFC */
    2862             : #endif /* CONFIG_WPS */
    2863             : #ifdef CONFIG_P2P_MANAGER
    2864        3094 :         } else if (os_strcmp(buf, "manage_p2p") == 0) {
    2865           5 :                 if (atoi(pos))
    2866           4 :                         bss->p2p |= P2P_MANAGE;
    2867             :                 else
    2868           1 :                         bss->p2p &= ~P2P_MANAGE;
    2869        3089 :         } else if (os_strcmp(buf, "allow_cross_connection") == 0) {
    2870           3 :                 if (atoi(pos))
    2871           1 :                         bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
    2872             :                 else
    2873           2 :                         bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
    2874             : #endif /* CONFIG_P2P_MANAGER */
    2875        3086 :         } else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
    2876           1 :                 bss->disassoc_low_ack = atoi(pos);
    2877        3085 :         } else if (os_strcmp(buf, "tdls_prohibit") == 0) {
    2878           1 :                 if (atoi(pos))
    2879           0 :                         bss->tdls |= TDLS_PROHIBIT;
    2880             :                 else
    2881           1 :                         bss->tdls &= ~TDLS_PROHIBIT;
    2882        3084 :         } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
    2883           1 :                 if (atoi(pos))
    2884           0 :                         bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
    2885             :                 else
    2886           1 :                         bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
    2887             : #ifdef CONFIG_RSN_TESTING
    2888             :         } else if (os_strcmp(buf, "rsn_testing") == 0) {
    2889             :                 extern int rsn_testing;
    2890             :                 rsn_testing = atoi(pos);
    2891             : #endif /* CONFIG_RSN_TESTING */
    2892        3083 :         } else if (os_strcmp(buf, "time_advertisement") == 0) {
    2893           6 :                 bss->time_advertisement = atoi(pos);
    2894        3077 :         } else if (os_strcmp(buf, "time_zone") == 0) {
    2895           7 :                 size_t tz_len = os_strlen(pos);
    2896           7 :                 if (tz_len < 4 || tz_len > 255) {
    2897           1 :                         wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone",
    2898             :                                    line);
    2899           1 :                         return 1;
    2900             :                 }
    2901           6 :                 os_free(bss->time_zone);
    2902           6 :                 bss->time_zone = os_strdup(pos);
    2903           6 :                 if (bss->time_zone == NULL)
    2904           0 :                         return 1;
    2905             : #ifdef CONFIG_WNM
    2906        3070 :         } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
    2907           6 :                 bss->wnm_sleep_mode = atoi(pos);
    2908        3064 :         } else if (os_strcmp(buf, "bss_transition") == 0) {
    2909          11 :                 bss->bss_transition = atoi(pos);
    2910             : #endif /* CONFIG_WNM */
    2911             : #ifdef CONFIG_INTERWORKING
    2912        3053 :         } else if (os_strcmp(buf, "interworking") == 0) {
    2913         119 :                 bss->interworking = atoi(pos);
    2914        2934 :         } else if (os_strcmp(buf, "access_network_type") == 0) {
    2915         120 :                 bss->access_network_type = atoi(pos);
    2916         239 :                 if (bss->access_network_type < 0 ||
    2917         119 :                     bss->access_network_type > 15) {
    2918           2 :                         wpa_printf(MSG_ERROR,
    2919             :                                    "Line %d: invalid access_network_type",
    2920             :                                    line);
    2921           2 :                         return 1;
    2922             :                 }
    2923        2814 :         } else if (os_strcmp(buf, "internet") == 0) {
    2924         118 :                 bss->internet = atoi(pos);
    2925        2696 :         } else if (os_strcmp(buf, "asra") == 0) {
    2926         118 :                 bss->asra = atoi(pos);
    2927        2578 :         } else if (os_strcmp(buf, "esr") == 0) {
    2928         118 :                 bss->esr = atoi(pos);
    2929        2460 :         } else if (os_strcmp(buf, "uesa") == 0) {
    2930         118 :                 bss->uesa = atoi(pos);
    2931        2342 :         } else if (os_strcmp(buf, "venue_group") == 0) {
    2932         117 :                 bss->venue_group = atoi(pos);
    2933         117 :                 bss->venue_info_set = 1;
    2934        2225 :         } else if (os_strcmp(buf, "venue_type") == 0) {
    2935         117 :                 bss->venue_type = atoi(pos);
    2936         117 :                 bss->venue_info_set = 1;
    2937        2108 :         } else if (os_strcmp(buf, "hessid") == 0) {
    2938          55 :                 if (hwaddr_aton(pos, bss->hessid)) {
    2939           1 :                         wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line);
    2940           1 :                         return 1;
    2941             :                 }
    2942        2053 :         } else if (os_strcmp(buf, "roaming_consortium") == 0) {
    2943         466 :                 if (parse_roaming_consortium(bss, pos, line) < 0)
    2944           3 :                         return 1;
    2945        1587 :         } else if (os_strcmp(buf, "venue_name") == 0) {
    2946         242 :                 if (parse_venue_name(bss, pos, line) < 0)
    2947           6 :                         return 1;
    2948        1345 :         } else if (os_strcmp(buf, "network_auth_type") == 0) {
    2949             :                 u8 auth_type;
    2950             :                 u16 redirect_url_len;
    2951          20 :                 if (hexstr2bin(pos, &auth_type, 1)) {
    2952           1 :                         wpa_printf(MSG_ERROR,
    2953             :                                    "Line %d: Invalid network_auth_type '%s'",
    2954             :                                    line, pos);
    2955           2 :                         return 1;
    2956             :                 }
    2957          19 :                 if (auth_type == 0 || auth_type == 2)
    2958          18 :                         redirect_url_len = os_strlen(pos + 2);
    2959             :                 else
    2960           1 :                         redirect_url_len = 0;
    2961          19 :                 os_free(bss->network_auth_type);
    2962          19 :                 bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1);
    2963          19 :                 if (bss->network_auth_type == NULL)
    2964           0 :                         return 1;
    2965          19 :                 *bss->network_auth_type = auth_type;
    2966          19 :                 WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len);
    2967          19 :                 if (redirect_url_len)
    2968          18 :                         os_memcpy(bss->network_auth_type + 3, pos + 2,
    2969             :                                   redirect_url_len);
    2970          19 :                 bss->network_auth_type_len = 3 + redirect_url_len;
    2971        1325 :         } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
    2972          19 :                 if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) {
    2973           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'",
    2974             :                                    line, pos);
    2975           1 :                         bss->ipaddr_type_configured = 0;
    2976           1 :                         return 1;
    2977             :                 }
    2978          18 :                 bss->ipaddr_type_configured = 1;
    2979        1306 :         } else if (os_strcmp(buf, "domain_name") == 0) {
    2980         114 :                 int j, num_domains, domain_len, domain_list_len = 0;
    2981             :                 char *tok_start, *tok_prev;
    2982             :                 u8 *domain_list, *domain_ptr;
    2983             : 
    2984         114 :                 domain_list_len = os_strlen(pos) + 1;
    2985         114 :                 domain_list = os_malloc(domain_list_len);
    2986         114 :                 if (domain_list == NULL)
    2987           0 :                         return 1;
    2988             : 
    2989         114 :                 domain_ptr = domain_list;
    2990         114 :                 tok_prev = pos;
    2991         114 :                 num_domains = 1;
    2992         324 :                 while ((tok_prev = os_strchr(tok_prev, ','))) {
    2993          96 :                         num_domains++;
    2994          96 :                         tok_prev++;
    2995             :                 }
    2996         114 :                 tok_prev = pos;
    2997         324 :                 for (j = 0; j < num_domains; j++) {
    2998         210 :                         tok_start = os_strchr(tok_prev, ',');
    2999         210 :                         if (tok_start) {
    3000          96 :                                 domain_len = tok_start - tok_prev;
    3001          96 :                                 *domain_ptr = domain_len;
    3002          96 :                                 os_memcpy(domain_ptr + 1, tok_prev, domain_len);
    3003          96 :                                 domain_ptr += domain_len + 1;
    3004          96 :                                 tok_prev = ++tok_start;
    3005             :                         } else {
    3006         114 :                                 domain_len = os_strlen(tok_prev);
    3007         114 :                                 *domain_ptr = domain_len;
    3008         114 :                                 os_memcpy(domain_ptr + 1, tok_prev, domain_len);
    3009         114 :                                 domain_ptr += domain_len + 1;
    3010             :                         }
    3011             :                 }
    3012             : 
    3013         114 :                 os_free(bss->domain_name);
    3014         114 :                 bss->domain_name = domain_list;
    3015         114 :                 bss->domain_name_len = domain_list_len;
    3016        1192 :         } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
    3017         123 :                 if (parse_3gpp_cell_net(bss, pos, line) < 0)
    3018           6 :                         return 1;
    3019        1069 :         } else if (os_strcmp(buf, "nai_realm") == 0) {
    3020         214 :                 if (parse_nai_realm(bss, pos, line) < 0)
    3021           7 :                         return 1;
    3022         855 :         } else if (os_strcmp(buf, "gas_frag_limit") == 0) {
    3023           0 :                 bss->gas_frag_limit = atoi(pos);
    3024         855 :         } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
    3025           1 :                 bss->gas_comeback_delay = atoi(pos);
    3026         854 :         } else if (os_strcmp(buf, "qos_map_set") == 0) {
    3027           7 :                 if (parse_qos_map_set(bss, pos, line) < 0)
    3028           6 :                         return 1;
    3029             : #endif /* CONFIG_INTERWORKING */
    3030             : #ifdef CONFIG_RADIUS_TEST
    3031             :         } else if (os_strcmp(buf, "dump_msk_file") == 0) {
    3032             :                 os_free(bss->dump_msk_file);
    3033             :                 bss->dump_msk_file = os_strdup(pos);
    3034             : #endif /* CONFIG_RADIUS_TEST */
    3035             : #ifdef CONFIG_HS20
    3036         847 :         } else if (os_strcmp(buf, "hs20") == 0) {
    3037         119 :                 bss->hs20 = atoi(pos);
    3038         728 :         } else if (os_strcmp(buf, "disable_dgaf") == 0) {
    3039           8 :                 bss->disable_dgaf = atoi(pos);
    3040         720 :         } else if (os_strcmp(buf, "proxy_arp") == 0) {
    3041           5 :                 bss->proxy_arp = atoi(pos);
    3042         715 :         } else if (os_strcmp(buf, "osen") == 0) {
    3043           1 :                 bss->osen = atoi(pos);
    3044         714 :         } else if (os_strcmp(buf, "anqp_domain_id") == 0) {
    3045           0 :                 bss->anqp_domain_id = atoi(pos);
    3046         714 :         } else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
    3047           1 :                 bss->hs20_deauth_req_timeout = atoi(pos);
    3048         713 :         } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
    3049          37 :                 if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
    3050           1 :                         return 1;
    3051         676 :         } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
    3052         123 :                 if (hs20_parse_wan_metrics(bss, pos, line) < 0)
    3053           6 :                         return 1;
    3054         553 :         } else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
    3055         358 :                 if (hs20_parse_conn_capab(bss, pos, line) < 0) {
    3056           2 :                         return 1;
    3057             :                 }
    3058         195 :         } else if (os_strcmp(buf, "hs20_operating_class") == 0) {
    3059             :                 u8 *oper_class;
    3060             :                 size_t oper_class_len;
    3061         120 :                 oper_class_len = os_strlen(pos);
    3062         120 :                 if (oper_class_len < 2 || (oper_class_len & 0x01)) {
    3063           1 :                         wpa_printf(MSG_ERROR,
    3064             :                                    "Line %d: Invalid hs20_operating_class '%s'",
    3065             :                                    line, pos);
    3066           1 :                         return 1;
    3067             :                 }
    3068         119 :                 oper_class_len /= 2;
    3069         119 :                 oper_class = os_malloc(oper_class_len);
    3070         119 :                 if (oper_class == NULL)
    3071           0 :                         return 1;
    3072         119 :                 if (hexstr2bin(pos, oper_class, oper_class_len)) {
    3073           1 :                         wpa_printf(MSG_ERROR,
    3074             :                                    "Line %d: Invalid hs20_operating_class '%s'",
    3075             :                                    line, pos);
    3076           1 :                         os_free(oper_class);
    3077           1 :                         return 1;
    3078             :                 }
    3079         118 :                 os_free(bss->hs20_operating_class);
    3080         118 :                 bss->hs20_operating_class = oper_class;
    3081         118 :                 bss->hs20_operating_class_len = oper_class_len;
    3082          75 :         } else if (os_strcmp(buf, "hs20_icon") == 0) {
    3083          10 :                 if (hs20_parse_icon(bss, pos) < 0) {
    3084           7 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
    3085             :                                    line, pos);
    3086           7 :                         return 1;
    3087             :                 }
    3088          65 :         } else if (os_strcmp(buf, "osu_ssid") == 0) {
    3089           7 :                 if (hs20_parse_osu_ssid(bss, pos, line) < 0)
    3090           4 :                         return 1;
    3091          58 :         } else if (os_strcmp(buf, "osu_server_uri") == 0) {
    3092           4 :                 if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
    3093           0 :                         return 1;
    3094          54 :         } else if (os_strcmp(buf, "osu_friendly_name") == 0) {
    3095           9 :                 if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
    3096           2 :                         return 1;
    3097          45 :         } else if (os_strcmp(buf, "osu_nai") == 0) {
    3098           2 :                 if (hs20_parse_osu_nai(bss, pos, line) < 0)
    3099           1 :                         return 1;
    3100          43 :         } else if (os_strcmp(buf, "osu_method_list") == 0) {
    3101           4 :                 if (hs20_parse_osu_method_list(bss, pos, line) < 0)
    3102           1 :                         return 1;
    3103          39 :         } else if (os_strcmp(buf, "osu_icon") == 0) {
    3104           4 :                 if (hs20_parse_osu_icon(bss, pos, line) < 0)
    3105           1 :                         return 1;
    3106          35 :         } else if (os_strcmp(buf, "osu_service_desc") == 0) {
    3107           8 :                 if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
    3108           2 :                         return 1;
    3109          27 :         } else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
    3110           1 :                 os_free(bss->subscr_remediation_url);
    3111           1 :                 bss->subscr_remediation_url = os_strdup(pos);
    3112          26 :         } else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
    3113           1 :                 bss->subscr_remediation_method = atoi(pos);
    3114             : #endif /* CONFIG_HS20 */
    3115             : #ifdef CONFIG_TESTING_OPTIONS
    3116             : #define PARSE_TEST_PROBABILITY(_val)                            \
    3117             :         } else if (os_strcmp(buf, #_val) == 0) {                \
    3118             :                 char *end;                                      \
    3119             :                                                                 \
    3120             :                 conf->_val = strtod(pos, &end);                  \
    3121             :                 if (*end || conf->_val < 0.0 ||                   \
    3122             :                     conf->_val > 1.0) {                           \
    3123             :                         wpa_printf(MSG_ERROR,                   \
    3124             :                                    "Line %d: Invalid value '%s'", \
    3125             :                                    line, pos);                  \
    3126             :                         return 1;                               \
    3127             :                 }
    3128          25 :         PARSE_TEST_PROBABILITY(ignore_probe_probability)
    3129          24 :         PARSE_TEST_PROBABILITY(ignore_auth_probability)
    3130          23 :         PARSE_TEST_PROBABILITY(ignore_assoc_probability)
    3131          22 :         PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
    3132          21 :         PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
    3133          21 :         } else if (os_strcmp(buf, "bss_load_test") == 0) {
    3134           6 :                 WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
    3135           6 :                 pos = os_strchr(pos, ':');
    3136           6 :                 if (pos == NULL) {
    3137           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
    3138             :                                    line);
    3139           2 :                         return 1;
    3140             :                 }
    3141           4 :                 pos++;
    3142           4 :                 bss->bss_load_test[2] = atoi(pos);
    3143           4 :                 pos = os_strchr(pos, ':');
    3144           4 :                 if (pos == NULL) {
    3145           1 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
    3146             :                                    line);
    3147           1 :                         return 1;
    3148             :                 }
    3149           3 :                 pos++;
    3150           3 :                 WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
    3151           3 :                 bss->bss_load_test_set = 1;
    3152          15 :         } else if (os_strcmp(buf, "radio_measurements") == 0) {
    3153           1 :                 bss->radio_measurements = atoi(pos);
    3154             : #endif /* CONFIG_TESTING_OPTIONS */
    3155          14 :         } else if (os_strcmp(buf, "vendor_elements") == 0) {
    3156             :                 struct wpabuf *elems;
    3157           3 :                 size_t len = os_strlen(pos);
    3158           3 :                 if (len & 0x01) {
    3159           1 :                         wpa_printf(MSG_ERROR,
    3160             :                                    "Line %d: Invalid vendor_elements '%s'",
    3161             :                                    line, pos);
    3162           1 :                         return 1;
    3163             :                 }
    3164           2 :                 len /= 2;
    3165           2 :                 if (len == 0) {
    3166           0 :                         wpabuf_free(bss->vendor_elements);
    3167           0 :                         bss->vendor_elements = NULL;
    3168           0 :                         return 0;
    3169             :                 }
    3170             : 
    3171           2 :                 elems = wpabuf_alloc(len);
    3172           2 :                 if (elems == NULL)
    3173           0 :                         return 1;
    3174             : 
    3175           2 :                 if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
    3176           1 :                         wpabuf_free(elems);
    3177           1 :                         wpa_printf(MSG_ERROR,
    3178             :                                    "Line %d: Invalid vendor_elements '%s'",
    3179             :                                    line, pos);
    3180           1 :                         return 1;
    3181             :                 }
    3182             : 
    3183           1 :                 wpabuf_free(bss->vendor_elements);
    3184           1 :                 bss->vendor_elements = elems;
    3185          11 :         } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
    3186           3 :                 bss->sae_anti_clogging_threshold = atoi(pos);
    3187           8 :         } else if (os_strcmp(buf, "sae_groups") == 0) {
    3188           2 :                 if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
    3189           0 :                         wpa_printf(MSG_ERROR,
    3190             :                                    "Line %d: Invalid sae_groups value '%s'",
    3191             :                                    line, pos);
    3192           0 :                         return 1;
    3193             :                 }
    3194           6 :         } else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
    3195           4 :                 int val = atoi(pos);
    3196           4 :                 if (val < 0 || val > 255) {
    3197           2 :                         wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
    3198             :                                    line, val);
    3199           2 :                         return 1;
    3200             :                 }
    3201           2 :                 conf->local_pwr_constraint = val;
    3202           2 :         } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
    3203           2 :                 conf->spectrum_mgmt_required = atoi(pos);
    3204           0 :         } else if (os_strcmp(buf, "wowlan_triggers") == 0) {
    3205           0 :                 os_free(bss->wowlan_triggers);
    3206           0 :                 bss->wowlan_triggers = os_strdup(pos);
    3207             :         } else {
    3208           0 :                 wpa_printf(MSG_ERROR,
    3209             :                            "Line %d: unknown configuration item '%s'",
    3210             :                            line, buf);
    3211           0 :                 return 1;
    3212             :         }
    3213             : 
    3214       16471 :         return 0;
    3215             : }
    3216             : 
    3217             : 
    3218             : /**
    3219             :  * hostapd_config_read - Read and parse a configuration file
    3220             :  * @fname: Configuration file name (including path, if needed)
    3221             :  * Returns: Allocated configuration data structure
    3222             :  */
    3223          65 : struct hostapd_config * hostapd_config_read(const char *fname)
    3224             : {
    3225             :         struct hostapd_config *conf;
    3226             :         FILE *f;
    3227             :         char buf[512], *pos;
    3228          65 :         int line = 0;
    3229          65 :         int errors = 0;
    3230             :         size_t i;
    3231             : 
    3232          65 :         f = fopen(fname, "r");
    3233          65 :         if (f == NULL) {
    3234           0 :                 wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
    3235             :                            "for reading.", fname);
    3236           0 :                 return NULL;
    3237             :         }
    3238             : 
    3239          65 :         conf = hostapd_config_defaults();
    3240          65 :         if (conf == NULL) {
    3241           1 :                 fclose(f);
    3242           1 :                 return NULL;
    3243             :         }
    3244             : 
    3245             :         /* set default driver based on configuration */
    3246          64 :         conf->driver = wpa_drivers[0];
    3247          64 :         if (conf->driver == NULL) {
    3248           0 :                 wpa_printf(MSG_ERROR, "No driver wrappers registered!");
    3249           0 :                 hostapd_config_free(conf);
    3250           0 :                 fclose(f);
    3251           0 :                 return NULL;
    3252             :         }
    3253             : 
    3254          64 :         conf->last_bss = conf->bss[0];
    3255             : 
    3256         932 :         while (fgets(buf, sizeof(buf), f)) {
    3257             :                 struct hostapd_bss_config *bss;
    3258             : 
    3259         804 :                 bss = conf->last_bss;
    3260         804 :                 line++;
    3261             : 
    3262         804 :                 if (buf[0] == '#')
    3263           4 :                         continue;
    3264         800 :                 pos = buf;
    3265       15009 :                 while (*pos != '\0') {
    3266       14209 :                         if (*pos == '\n') {
    3267         800 :                                 *pos = '\0';
    3268         800 :                                 break;
    3269             :                         }
    3270       13409 :                         pos++;
    3271             :                 }
    3272         800 :                 if (buf[0] == '\0')
    3273         136 :                         continue;
    3274             : 
    3275         664 :                 pos = os_strchr(buf, '=');
    3276         664 :                 if (pos == NULL) {
    3277           0 :                         wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
    3278             :                                    line, buf);
    3279           0 :                         errors++;
    3280           0 :                         continue;
    3281             :                 }
    3282         664 :                 *pos = '\0';
    3283         664 :                 pos++;
    3284         664 :                 errors += hostapd_config_fill(conf, bss, buf, pos, line);
    3285             :         }
    3286             : 
    3287          64 :         fclose(f);
    3288             : 
    3289         134 :         for (i = 0; i < conf->num_bss; i++)
    3290          70 :                 hostapd_set_security_params(conf->bss[i], 1);
    3291             : 
    3292          64 :         if (hostapd_config_check(conf, 1))
    3293           0 :                 errors++;
    3294             : 
    3295             : #ifndef WPA_IGNORE_CONFIG_ERRORS
    3296          64 :         if (errors) {
    3297           0 :                 wpa_printf(MSG_ERROR, "%d errors found in configuration file "
    3298             :                            "'%s'", errors, fname);
    3299           0 :                 hostapd_config_free(conf);
    3300           0 :                 conf = NULL;
    3301             :         }
    3302             : #endif /* WPA_IGNORE_CONFIG_ERRORS */
    3303             : 
    3304          64 :         return conf;
    3305             : }
    3306             : 
    3307             : 
    3308       15991 : int hostapd_set_iface(struct hostapd_config *conf,
    3309             :                       struct hostapd_bss_config *bss, char *field, char *value)
    3310             : {
    3311             :         int errors;
    3312             :         size_t i;
    3313             : 
    3314       15991 :         errors = hostapd_config_fill(conf, bss, field, value, 0);
    3315       15991 :         if (errors) {
    3316         174 :                 wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
    3317             :                            "to value '%s'", field, value);
    3318         174 :                 return -1;
    3319             :         }
    3320             : 
    3321       31642 :         for (i = 0; i < conf->num_bss; i++)
    3322       15825 :                 hostapd_set_security_params(conf->bss[i], 0);
    3323             : 
    3324       15817 :         if (hostapd_config_check(conf, 0)) {
    3325           1 :                 wpa_printf(MSG_ERROR, "Configuration check failed");
    3326           1 :                 return -1;
    3327             :         }
    3328             : 
    3329       15816 :         return 0;
    3330             : }

Generated by: LCOV version 1.10