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