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 1443382998 Lines: 2042 2299 88.8 %
Date: 2015-09-27 Functions: 42 42 100.0 %

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

Generated by: LCOV version 1.10