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 1401264779 Lines: 1877 2139 87.8 %
Date: 2014-05-28 Functions: 40 40 100.0 %

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

Generated by: LCOV version 1.10