Convert remaining SSID routines from char* to u8*
[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(*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(*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         size_t len;
571
572         secret = os_strchr(val, ' ');
573         if (secret == NULL)
574                 return -1;
575
576         secret++;
577         len = os_strlen(secret);
578
579         if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
580                 return -1;
581
582         os_free(bss->radius_das_shared_secret);
583         bss->radius_das_shared_secret = os_malloc(len);
584         if (bss->radius_das_shared_secret == NULL)
585                 return -1;
586
587         os_memcpy(bss->radius_das_shared_secret, secret, len);
588         bss->radius_das_shared_secret_len = len;
589
590         return 0;
591 }
592 #endif /* CONFIG_NO_RADIUS */
593
594
595 static int hostapd_config_parse_key_mgmt(int line, const char *value)
596 {
597         int val = 0, last;
598         char *start, *end, *buf;
599
600         buf = os_strdup(value);
601         if (buf == NULL)
602                 return -1;
603         start = buf;
604
605         while (*start != '\0') {
606                 while (*start == ' ' || *start == '\t')
607                         start++;
608                 if (*start == '\0')
609                         break;
610                 end = start;
611                 while (*end != ' ' && *end != '\t' && *end != '\0')
612                         end++;
613                 last = *end == '\0';
614                 *end = '\0';
615                 if (os_strcmp(start, "WPA-PSK") == 0)
616                         val |= WPA_KEY_MGMT_PSK;
617                 else if (os_strcmp(start, "WPA-EAP") == 0)
618                         val |= WPA_KEY_MGMT_IEEE8021X;
619 #ifdef CONFIG_IEEE80211R
620                 else if (os_strcmp(start, "FT-PSK") == 0)
621                         val |= WPA_KEY_MGMT_FT_PSK;
622                 else if (os_strcmp(start, "FT-EAP") == 0)
623                         val |= WPA_KEY_MGMT_FT_IEEE8021X;
624 #endif /* CONFIG_IEEE80211R */
625 #ifdef CONFIG_IEEE80211W
626                 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
627                         val |= WPA_KEY_MGMT_PSK_SHA256;
628                 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
629                         val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
630 #endif /* CONFIG_IEEE80211W */
631                 else {
632                         wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
633                                    line, start);
634                         os_free(buf);
635                         return -1;
636                 }
637
638                 if (last)
639                         break;
640                 start = end + 1;
641         }
642
643         os_free(buf);
644         if (val == 0) {
645                 wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values "
646                            "configured.", line);
647                 return -1;
648         }
649
650         return val;
651 }
652
653
654 static int hostapd_config_parse_cipher(int line, const char *value)
655 {
656         int val = 0, last;
657         char *start, *end, *buf;
658
659         buf = os_strdup(value);
660         if (buf == NULL)
661                 return -1;
662         start = buf;
663
664         while (*start != '\0') {
665                 while (*start == ' ' || *start == '\t')
666                         start++;
667                 if (*start == '\0')
668                         break;
669                 end = start;
670                 while (*end != ' ' && *end != '\t' && *end != '\0')
671                         end++;
672                 last = *end == '\0';
673                 *end = '\0';
674                 if (os_strcmp(start, "CCMP") == 0)
675                         val |= WPA_CIPHER_CCMP;
676                 else if (os_strcmp(start, "TKIP") == 0)
677                         val |= WPA_CIPHER_TKIP;
678                 else if (os_strcmp(start, "WEP104") == 0)
679                         val |= WPA_CIPHER_WEP104;
680                 else if (os_strcmp(start, "WEP40") == 0)
681                         val |= WPA_CIPHER_WEP40;
682                 else if (os_strcmp(start, "NONE") == 0)
683                         val |= WPA_CIPHER_NONE;
684                 else {
685                         wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
686                                    line, start);
687                         os_free(buf);
688                         return -1;
689                 }
690
691                 if (last)
692                         break;
693                 start = end + 1;
694         }
695         os_free(buf);
696
697         if (val == 0) {
698                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
699                            line);
700                 return -1;
701         }
702         return val;
703 }
704
705
706 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
707                                    char *val)
708 {
709         size_t len = os_strlen(val);
710
711         if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL)
712                 return -1;
713
714         if (val[0] == '"') {
715                 if (len < 2 || val[len - 1] != '"')
716                         return -1;
717                 len -= 2;
718                 wep->key[keyidx] = os_malloc(len);
719                 if (wep->key[keyidx] == NULL)
720                         return -1;
721                 os_memcpy(wep->key[keyidx], val + 1, len);
722                 wep->len[keyidx] = len;
723         } else {
724                 if (len & 1)
725                         return -1;
726                 len /= 2;
727                 wep->key[keyidx] = os_malloc(len);
728                 if (wep->key[keyidx] == NULL)
729                         return -1;
730                 wep->len[keyidx] = len;
731                 if (hexstr2bin(val, wep->key[keyidx], len) < 0)
732                         return -1;
733         }
734
735         wep->keys_set++;
736
737         return 0;
738 }
739
740
741 static int hostapd_parse_rates(int **rate_list, char *val)
742 {
743         int *list;
744         int count;
745         char *pos, *end;
746
747         os_free(*rate_list);
748         *rate_list = NULL;
749
750         pos = val;
751         count = 0;
752         while (*pos != '\0') {
753                 if (*pos == ' ')
754                         count++;
755                 pos++;
756         }
757
758         list = os_malloc(sizeof(int) * (count + 2));
759         if (list == NULL)
760                 return -1;
761         pos = val;
762         count = 0;
763         while (*pos != '\0') {
764                 end = os_strchr(pos, ' ');
765                 if (end)
766                         *end = '\0';
767
768                 list[count++] = atoi(pos);
769                 if (!end)
770                         break;
771                 pos = end + 1;
772         }
773         list[count] = -1;
774
775         *rate_list = list;
776         return 0;
777 }
778
779
780 static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
781 {
782         struct hostapd_bss_config *bss;
783
784         if (*ifname == '\0')
785                 return -1;
786
787         bss = os_realloc(conf->bss, (conf->num_bss + 1) *
788                          sizeof(struct hostapd_bss_config));
789         if (bss == NULL) {
790                 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
791                            "multi-BSS entry");
792                 return -1;
793         }
794         conf->bss = bss;
795
796         bss = &(conf->bss[conf->num_bss]);
797         os_memset(bss, 0, sizeof(*bss));
798         bss->radius = os_zalloc(sizeof(*bss->radius));
799         if (bss->radius == NULL) {
800                 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
801                            "multi-BSS RADIUS data");
802                 return -1;
803         }
804
805         conf->num_bss++;
806         conf->last_bss = bss;
807
808         hostapd_config_defaults_bss(bss);
809         os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
810         os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
811
812         return 0;
813 }
814
815
816 /* convert floats with one decimal place to value*10 int, i.e.,
817  * "1.5" will return 15 */
818 static int hostapd_config_read_int10(const char *value)
819 {
820         int i, d;
821         char *pos;
822
823         i = atoi(value);
824         pos = os_strchr(value, '.');
825         d = 0;
826         if (pos) {
827                 pos++;
828                 if (*pos >= '0' && *pos <= '9')
829                         d = *pos - '0';
830         }
831
832         return i * 10 + d;
833 }
834
835
836 static int valid_cw(int cw)
837 {
838         return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
839                 cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023);
840 }
841
842
843 enum {
844         IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
845         IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
846         IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
847         IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
848 };
849
850 static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
851                                    char *val)
852 {
853         int num;
854         char *pos;
855         struct hostapd_tx_queue_params *queue;
856
857         /* skip 'tx_queue_' prefix */
858         pos = name + 9;
859         if (os_strncmp(pos, "data", 4) == 0 &&
860             pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
861                 num = pos[4] - '0';
862                 pos += 6;
863         } else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
864                    os_strncmp(pos, "beacon_", 7) == 0) {
865                 wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
866                 return 0;
867         } else {
868                 wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
869                 return -1;
870         }
871
872         if (num >= NUM_TX_QUEUES) {
873                 /* for backwards compatibility, do not trigger failure */
874                 wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
875                 return 0;
876         }
877
878         queue = &conf->tx_queue[num];
879
880         if (os_strcmp(pos, "aifs") == 0) {
881                 queue->aifs = atoi(val);
882                 if (queue->aifs < 0 || queue->aifs > 255) {
883                         wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
884                                    queue->aifs);
885                         return -1;
886                 }
887         } else if (os_strcmp(pos, "cwmin") == 0) {
888                 queue->cwmin = atoi(val);
889                 if (!valid_cw(queue->cwmin)) {
890                         wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
891                                    queue->cwmin);
892                         return -1;
893                 }
894         } else if (os_strcmp(pos, "cwmax") == 0) {
895                 queue->cwmax = atoi(val);
896                 if (!valid_cw(queue->cwmax)) {
897                         wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
898                                    queue->cwmax);
899                         return -1;
900                 }
901         } else if (os_strcmp(pos, "burst") == 0) {
902                 queue->burst = hostapd_config_read_int10(val);
903         } else {
904                 wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
905                 return -1;
906         }
907
908         return 0;
909 }
910
911
912 static int hostapd_config_wmm_ac(struct hostapd_config *conf, char *name,
913                                  char *val)
914 {
915         int num, v;
916         char *pos;
917         struct hostapd_wmm_ac_params *ac;
918
919         /* skip 'wme_ac_' or 'wmm_ac_' prefix */
920         pos = name + 7;
921         if (os_strncmp(pos, "be_", 3) == 0) {
922                 num = 0;
923                 pos += 3;
924         } else if (os_strncmp(pos, "bk_", 3) == 0) {
925                 num = 1;
926                 pos += 3;
927         } else if (os_strncmp(pos, "vi_", 3) == 0) {
928                 num = 2;
929                 pos += 3;
930         } else if (os_strncmp(pos, "vo_", 3) == 0) {
931                 num = 3;
932                 pos += 3;
933         } else {
934                 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
935                 return -1;
936         }
937
938         ac = &conf->wmm_ac_params[num];
939
940         if (os_strcmp(pos, "aifs") == 0) {
941                 v = atoi(val);
942                 if (v < 1 || v > 255) {
943                         wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
944                         return -1;
945                 }
946                 ac->aifs = v;
947         } else if (os_strcmp(pos, "cwmin") == 0) {
948                 v = atoi(val);
949                 if (v < 0 || v > 12) {
950                         wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
951                         return -1;
952                 }
953                 ac->cwmin = v;
954         } else if (os_strcmp(pos, "cwmax") == 0) {
955                 v = atoi(val);
956                 if (v < 0 || v > 12) {
957                         wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
958                         return -1;
959                 }
960                 ac->cwmax = v;
961         } else if (os_strcmp(pos, "txop_limit") == 0) {
962                 v = atoi(val);
963                 if (v < 0 || v > 0xffff) {
964                         wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
965                         return -1;
966                 }
967                 ac->txop_limit = v;
968         } else if (os_strcmp(pos, "acm") == 0) {
969                 v = atoi(val);
970                 if (v < 0 || v > 1) {
971                         wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
972                         return -1;
973                 }
974                 ac->admission_control_mandatory = v;
975         } else {
976                 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
977                 return -1;
978         }
979
980         return 0;
981 }
982
983
984 #ifdef CONFIG_IEEE80211R
985 static int add_r0kh(struct hostapd_bss_config *bss, char *value)
986 {
987         struct ft_remote_r0kh *r0kh;
988         char *pos, *next;
989
990         r0kh = os_zalloc(sizeof(*r0kh));
991         if (r0kh == NULL)
992                 return -1;
993
994         /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
995         pos = value;
996         next = os_strchr(pos, ' ');
997         if (next)
998                 *next++ = '\0';
999         if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
1000                 wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos);
1001                 os_free(r0kh);
1002                 return -1;
1003         }
1004
1005         pos = next;
1006         next = os_strchr(pos, ' ');
1007         if (next)
1008                 *next++ = '\0';
1009         if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
1010                 wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos);
1011                 os_free(r0kh);
1012                 return -1;
1013         }
1014         r0kh->id_len = next - pos - 1;
1015         os_memcpy(r0kh->id, pos, r0kh->id_len);
1016
1017         pos = next;
1018         if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) {
1019                 wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos);
1020                 os_free(r0kh);
1021                 return -1;
1022         }
1023
1024         r0kh->next = bss->r0kh_list;
1025         bss->r0kh_list = r0kh;
1026
1027         return 0;
1028 }
1029
1030
1031 static int add_r1kh(struct hostapd_bss_config *bss, char *value)
1032 {
1033         struct ft_remote_r1kh *r1kh;
1034         char *pos, *next;
1035
1036         r1kh = os_zalloc(sizeof(*r1kh));
1037         if (r1kh == NULL)
1038                 return -1;
1039
1040         /* 02:01:02:03:04:05 02:01:02:03:04:05
1041          * 000102030405060708090a0b0c0d0e0f */
1042         pos = value;
1043         next = os_strchr(pos, ' ');
1044         if (next)
1045                 *next++ = '\0';
1046         if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
1047                 wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos);
1048                 os_free(r1kh);
1049                 return -1;
1050         }
1051
1052         pos = next;
1053         next = os_strchr(pos, ' ');
1054         if (next)
1055                 *next++ = '\0';
1056         if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
1057                 wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos);
1058                 os_free(r1kh);
1059                 return -1;
1060         }
1061
1062         pos = next;
1063         if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) {
1064                 wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos);
1065                 os_free(r1kh);
1066                 return -1;
1067         }
1068
1069         r1kh->next = bss->r1kh_list;
1070         bss->r1kh_list = r1kh;
1071
1072         return 0;
1073 }
1074 #endif /* CONFIG_IEEE80211R */
1075
1076
1077 #ifdef CONFIG_IEEE80211N
1078 static int hostapd_config_ht_capab(struct hostapd_config *conf,
1079                                    const char *capab)
1080 {
1081         if (os_strstr(capab, "[LDPC]"))
1082                 conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
1083         if (os_strstr(capab, "[HT40-]")) {
1084                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1085                 conf->secondary_channel = -1;
1086         }
1087         if (os_strstr(capab, "[HT40+]")) {
1088                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1089                 conf->secondary_channel = 1;
1090         }
1091         if (os_strstr(capab, "[SMPS-STATIC]")) {
1092                 conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
1093                 conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
1094         }
1095         if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
1096                 conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
1097                 conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
1098         }
1099         if (os_strstr(capab, "[GF]"))
1100                 conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
1101         if (os_strstr(capab, "[SHORT-GI-20]"))
1102                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
1103         if (os_strstr(capab, "[SHORT-GI-40]"))
1104                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
1105         if (os_strstr(capab, "[TX-STBC]"))
1106                 conf->ht_capab |= HT_CAP_INFO_TX_STBC;
1107         if (os_strstr(capab, "[RX-STBC1]")) {
1108                 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1109                 conf->ht_capab |= HT_CAP_INFO_RX_STBC_1;
1110         }
1111         if (os_strstr(capab, "[RX-STBC12]")) {
1112                 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1113                 conf->ht_capab |= HT_CAP_INFO_RX_STBC_12;
1114         }
1115         if (os_strstr(capab, "[RX-STBC123]")) {
1116                 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1117                 conf->ht_capab |= HT_CAP_INFO_RX_STBC_123;
1118         }
1119         if (os_strstr(capab, "[DELAYED-BA]"))
1120                 conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
1121         if (os_strstr(capab, "[MAX-AMSDU-7935]"))
1122                 conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
1123         if (os_strstr(capab, "[DSSS_CCK-40]"))
1124                 conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
1125         if (os_strstr(capab, "[PSMP]"))
1126                 conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP;
1127         if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
1128                 conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
1129
1130         return 0;
1131 }
1132 #endif /* CONFIG_IEEE80211N */
1133
1134
1135 #ifdef CONFIG_IEEE80211AC
1136 static int hostapd_config_vht_capab(struct hostapd_config *conf,
1137                                     const char *capab)
1138 {
1139         if (os_strstr(capab, "[MAX-MPDU-7991]"))
1140                 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
1141         if (os_strstr(capab, "[MAX-MPDU-11454]"))
1142                 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
1143         if (os_strstr(capab, "[VHT160]"))
1144                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1145         if (os_strstr(capab, "[VHT160-80PLUS80]"))
1146                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1147         if (os_strstr(capab, "[VHT160-80PLUS80]"))
1148                 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1149         if (os_strstr(capab, "[RXLDPC]"))
1150                 conf->vht_capab |= VHT_CAP_RXLDPC;
1151         if (os_strstr(capab, "[SHORT-GI-80]"))
1152                 conf->vht_capab |= VHT_CAP_SHORT_GI_80;
1153         if (os_strstr(capab, "[SHORT-GI-160]"))
1154                 conf->vht_capab |= VHT_CAP_SHORT_GI_160;
1155         if (os_strstr(capab, "[TX-STBC-2BY1]"))
1156                 conf->vht_capab |= VHT_CAP_TXSTBC;
1157         if (os_strstr(capab, "[RX-STBC-1]"))
1158                 conf->vht_capab |= VHT_CAP_RXSTBC_1;
1159         if (os_strstr(capab, "[RX-STBC-12]"))
1160                 conf->vht_capab |= VHT_CAP_RXSTBC_2;
1161         if (os_strstr(capab, "[RX-STBC-123]"))
1162                 conf->vht_capab |= VHT_CAP_RXSTBC_3;
1163         if (os_strstr(capab, "[RX-STBC-1234]"))
1164                 conf->vht_capab |= VHT_CAP_RXSTBC_4;
1165         if (os_strstr(capab, "[SU-BEAMFORMER]"))
1166                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
1167         if (os_strstr(capab, "[SU-BEAMFORMEE]"))
1168                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1169         if (os_strstr(capab, "[BF-ANTENNA-2]") &&
1170             (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
1171                 conf->vht_capab |= VHT_CAP_BEAMFORMER_ANTENNAS_MAX;
1172         if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
1173             (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
1174                 conf->vht_capab |= VHT_CAP_SOUNDING_DIMENTION_MAX;
1175         if (os_strstr(capab, "[MU-BEAMFORMER]"))
1176                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
1177         if (os_strstr(capab, "[MU-BEAMFORMEE]"))
1178                 conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1179         if (os_strstr(capab, "[VHT-TXOP-PS]"))
1180                 conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
1181         if (os_strstr(capab, "[HTC-VHT]"))
1182                 conf->vht_capab |= VHT_CAP_HTC_VHT;
1183         if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP0]"))
1184                 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT;
1185         if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
1186             (conf->vht_capab & VHT_CAP_HTC_VHT))
1187                 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
1188         if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
1189             (conf->vht_capab & VHT_CAP_HTC_VHT))
1190                 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
1191         if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
1192                 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
1193         if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
1194                 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
1195         return 0;
1196 }
1197 #endif /* CONFIG_IEEE80211AC */
1198
1199
1200 static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
1201                                     struct hostapd_config *conf)
1202 {
1203         if (bss->ieee802_1x && !bss->eap_server &&
1204             !bss->radius->auth_servers) {
1205                 wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
1206                            "EAP authenticator configured).");
1207                 return -1;
1208         }
1209
1210         if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
1211             bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1212                 wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
1213                            "RADIUS checking (macaddr_acl=2) enabled.");
1214                 return -1;
1215         }
1216
1217         if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
1218             bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
1219             bss->ssid.wpa_psk_file == NULL &&
1220             (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
1221              bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
1222                 wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
1223                            "is not configured.");
1224                 return -1;
1225         }
1226
1227         if (hostapd_mac_comp_empty(bss->bssid) != 0) {
1228                 size_t i;
1229
1230                 for (i = 0; i < conf->num_bss; i++) {
1231                         if ((&conf->bss[i] != bss) &&
1232                             (hostapd_mac_comp(conf->bss[i].bssid,
1233                                               bss->bssid) == 0)) {
1234                                 wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
1235                                            " on interface '%s' and '%s'.",
1236                                            MAC2STR(bss->bssid),
1237                                            conf->bss[i].iface, bss->iface);
1238                                 return -1;
1239                         }
1240                 }
1241         }
1242
1243 #ifdef CONFIG_IEEE80211R
1244         if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
1245             (bss->nas_identifier == NULL ||
1246              os_strlen(bss->nas_identifier) < 1 ||
1247              os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
1248                 wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires "
1249                            "nas_identifier to be configured as a 1..48 octet "
1250                            "string");
1251                 return -1;
1252         }
1253 #endif /* CONFIG_IEEE80211R */
1254
1255 #ifdef CONFIG_IEEE80211N
1256         if (conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
1257                 bss->disable_11n = 1;
1258                 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
1259                            "allowed, disabling HT capabilites");
1260         }
1261
1262         if (conf->ieee80211n &&
1263             bss->ssid.security_policy == SECURITY_STATIC_WEP) {
1264                 bss->disable_11n = 1;
1265                 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
1266                            "allowed, disabling HT capabilities");
1267         }
1268
1269         if (conf->ieee80211n && bss->wpa &&
1270             !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
1271             !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) {
1272                 bss->disable_11n = 1;
1273                 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
1274                            "requires CCMP to be enabled, disabling HT "
1275                            "capabilities");
1276         }
1277 #endif /* CONFIG_IEEE80211N */
1278
1279 #ifdef CONFIG_WPS2
1280         if (bss->wps_state && bss->ignore_broadcast_ssid) {
1281                 wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
1282                            "configuration forced WPS to be disabled");
1283                 bss->wps_state = 0;
1284         }
1285
1286         if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) {
1287                 wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
1288                            "disabled");
1289                 bss->wps_state = 0;
1290         }
1291 #endif /* CONFIG_WPS2 */
1292
1293         return 0;
1294 }
1295
1296
1297 static int hostapd_config_check(struct hostapd_config *conf)
1298 {
1299         size_t i;
1300
1301         if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) {
1302                 wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
1303                            "setting the country_code");
1304                 return -1;
1305         }
1306
1307         for (i = 0; i < conf->num_bss; i++) {
1308                 if (hostapd_config_check_bss(&conf->bss[i], conf))
1309                         return -1;
1310         }
1311
1312         return 0;
1313 }
1314
1315
1316 #ifdef CONFIG_INTERWORKING
1317 static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
1318                                     int line)
1319 {
1320         size_t len = os_strlen(pos);
1321         u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
1322
1323         struct hostapd_roaming_consortium *rc;
1324
1325         if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
1326             hexstr2bin(pos, oi, len / 2)) {
1327                 wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
1328                            "'%s'", line, pos);
1329                 return -1;
1330         }
1331         len /= 2;
1332
1333         rc = os_realloc(bss->roaming_consortium,
1334                         sizeof(struct hostapd_roaming_consortium) *
1335                         (bss->roaming_consortium_count + 1));
1336         if (rc == NULL)
1337                 return -1;
1338
1339         os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
1340         rc[bss->roaming_consortium_count].len = len;
1341
1342         bss->roaming_consortium = rc;
1343         bss->roaming_consortium_count++;
1344
1345         return 0;
1346 }
1347
1348
1349 static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
1350                             int line)
1351 {
1352         char *sep;
1353         size_t clen, nlen;
1354         struct hostapd_venue_name *vn;
1355
1356         sep = os_strchr(pos, ':');
1357         if (sep == NULL)
1358                 goto fail;
1359         *sep++ = '\0';
1360
1361         clen = os_strlen(pos);
1362         if (clen < 2)
1363                 goto fail;
1364         nlen = os_strlen(sep);
1365         if (nlen > 252)
1366                 goto fail;
1367
1368         vn = os_realloc(bss->venue_name,
1369                         sizeof(struct hostapd_venue_name) *
1370                         (bss->venue_name_count + 1));
1371         if (vn == NULL)
1372                 return -1;
1373
1374         bss->venue_name = vn;
1375         vn = &bss->venue_name[bss->venue_name_count];
1376         bss->venue_name_count++;
1377
1378         os_memset(vn->lang, 0, sizeof(vn->lang));
1379         os_memcpy(vn->lang, pos, clen);
1380         vn->name_len = nlen;
1381         os_memcpy(vn->name, sep, nlen);
1382
1383         return 0;
1384
1385 fail:
1386         wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
1387                    line, pos);
1388         return -1;
1389 }
1390 #endif /* CONFIG_INTERWORKING */
1391
1392
1393 #ifdef CONFIG_WPS_NFC
1394 static struct wpabuf * hostapd_parse_bin(const char *buf)
1395 {
1396         size_t len;
1397         struct wpabuf *ret;
1398
1399         len = os_strlen(buf);
1400         if (len & 0x01)
1401                 return NULL;
1402         len /= 2;
1403
1404         ret = wpabuf_alloc(len);
1405         if (ret == NULL)
1406                 return NULL;
1407
1408         if (hexstr2bin(buf, wpabuf_put(ret, len), len)) {
1409                 wpabuf_free(ret);
1410                 return NULL;
1411         }
1412
1413         return ret;
1414 }
1415 #endif /* CONFIG_WPS_NFC */
1416
1417
1418 static int hostapd_config_fill(struct hostapd_config *conf,
1419                                struct hostapd_bss_config *bss,
1420                                char *buf, char *pos, int line)
1421 {
1422         int errors = 0;
1423
1424         {
1425                 if (os_strcmp(buf, "interface") == 0) {
1426                         os_strlcpy(conf->bss[0].iface, pos,
1427                                    sizeof(conf->bss[0].iface));
1428                 } else if (os_strcmp(buf, "bridge") == 0) {
1429                         os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
1430                 } else if (os_strcmp(buf, "wds_bridge") == 0) {
1431                         os_strlcpy(bss->wds_bridge, pos,
1432                                    sizeof(bss->wds_bridge));
1433                 } else if (os_strcmp(buf, "driver") == 0) {
1434                         int j;
1435                         /* clear to get error below if setting is invalid */
1436                         conf->driver = NULL;
1437                         for (j = 0; wpa_drivers[j]; j++) {
1438                                 if (os_strcmp(pos, wpa_drivers[j]->name) == 0)
1439                                 {
1440                                         conf->driver = wpa_drivers[j];
1441                                         break;
1442                                 }
1443                         }
1444                         if (conf->driver == NULL) {
1445                                 wpa_printf(MSG_ERROR, "Line %d: invalid/"
1446                                            "unknown driver '%s'", line, pos);
1447                                 errors++;
1448                         }
1449                 } else if (os_strcmp(buf, "debug") == 0) {
1450                         wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' "
1451                                    "configuration variable is not used "
1452                                    "anymore", line);
1453                 } else if (os_strcmp(buf, "logger_syslog_level") == 0) {
1454                         bss->logger_syslog_level = atoi(pos);
1455                 } else if (os_strcmp(buf, "logger_stdout_level") == 0) {
1456                         bss->logger_stdout_level = atoi(pos);
1457                 } else if (os_strcmp(buf, "logger_syslog") == 0) {
1458                         bss->logger_syslog = atoi(pos);
1459                 } else if (os_strcmp(buf, "logger_stdout") == 0) {
1460                         bss->logger_stdout = atoi(pos);
1461                 } else if (os_strcmp(buf, "dump_file") == 0) {
1462                         bss->dump_log_name = os_strdup(pos);
1463                 } else if (os_strcmp(buf, "ssid") == 0) {
1464                         bss->ssid.ssid_len = os_strlen(pos);
1465                         if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
1466                             bss->ssid.ssid_len < 1) {
1467                                 wpa_printf(MSG_ERROR, "Line %d: invalid SSID "
1468                                            "'%s'", line, pos);
1469                                 errors++;
1470                         } else {
1471                                 os_memcpy(bss->ssid.ssid, pos,
1472                                           bss->ssid.ssid_len);
1473                                 bss->ssid.ssid_set = 1;
1474                         }
1475                 } else if (os_strcmp(buf, "macaddr_acl") == 0) {
1476                         bss->macaddr_acl = atoi(pos);
1477                         if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
1478                             bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
1479                             bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1480                                 wpa_printf(MSG_ERROR, "Line %d: unknown "
1481                                            "macaddr_acl %d",
1482                                            line, bss->macaddr_acl);
1483                         }
1484                 } else if (os_strcmp(buf, "accept_mac_file") == 0) {
1485                         if (hostapd_config_read_maclist(pos, &bss->accept_mac,
1486                                                         &bss->num_accept_mac))
1487                         {
1488                                 wpa_printf(MSG_ERROR, "Line %d: Failed to "
1489                                            "read accept_mac_file '%s'",
1490                                            line, pos);
1491                                 errors++;
1492                         }
1493                 } else if (os_strcmp(buf, "deny_mac_file") == 0) {
1494                         if (hostapd_config_read_maclist(pos, &bss->deny_mac,
1495                                                         &bss->num_deny_mac)) {
1496                                 wpa_printf(MSG_ERROR, "Line %d: Failed to "
1497                                            "read deny_mac_file '%s'",
1498                                            line, pos);
1499                                 errors++;
1500                         }
1501                 } else if (os_strcmp(buf, "wds_sta") == 0) {
1502                         bss->wds_sta = atoi(pos);
1503                 } else if (os_strcmp(buf, "ap_isolate") == 0) {
1504                         bss->isolate = atoi(pos);
1505                 } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
1506                         bss->ap_max_inactivity = atoi(pos);
1507                 } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
1508                         bss->skip_inactivity_poll = atoi(pos);
1509                 } else if (os_strcmp(buf, "country_code") == 0) {
1510                         os_memcpy(conf->country, pos, 2);
1511                         /* FIX: make this configurable */
1512                         conf->country[2] = ' ';
1513                 } else if (os_strcmp(buf, "ieee80211d") == 0) {
1514                         conf->ieee80211d = atoi(pos);
1515                 } else if (os_strcmp(buf, "ieee8021x") == 0) {
1516                         bss->ieee802_1x = atoi(pos);
1517                 } else if (os_strcmp(buf, "eapol_version") == 0) {
1518                         bss->eapol_version = atoi(pos);
1519                         if (bss->eapol_version < 1 ||
1520                             bss->eapol_version > 2) {
1521                                 wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL "
1522                                            "version (%d): '%s'.",
1523                                            line, bss->eapol_version, pos);
1524                                 errors++;
1525                         } else
1526                                 wpa_printf(MSG_DEBUG, "eapol_version=%d",
1527                                            bss->eapol_version);
1528 #ifdef EAP_SERVER
1529                 } else if (os_strcmp(buf, "eap_authenticator") == 0) {
1530                         bss->eap_server = atoi(pos);
1531                         wpa_printf(MSG_ERROR, "Line %d: obsolete "
1532                                    "eap_authenticator used; this has been "
1533                                    "renamed to eap_server", line);
1534                 } else if (os_strcmp(buf, "eap_server") == 0) {
1535                         bss->eap_server = atoi(pos);
1536                 } else if (os_strcmp(buf, "eap_user_file") == 0) {
1537                         if (hostapd_config_read_eap_user(pos, bss))
1538                                 errors++;
1539                 } else if (os_strcmp(buf, "ca_cert") == 0) {
1540                         os_free(bss->ca_cert);
1541                         bss->ca_cert = os_strdup(pos);
1542                 } else if (os_strcmp(buf, "server_cert") == 0) {
1543                         os_free(bss->server_cert);
1544                         bss->server_cert = os_strdup(pos);
1545                 } else if (os_strcmp(buf, "private_key") == 0) {
1546                         os_free(bss->private_key);
1547                         bss->private_key = os_strdup(pos);
1548                 } else if (os_strcmp(buf, "private_key_passwd") == 0) {
1549                         os_free(bss->private_key_passwd);
1550                         bss->private_key_passwd = os_strdup(pos);
1551                 } else if (os_strcmp(buf, "check_crl") == 0) {
1552                         bss->check_crl = atoi(pos);
1553                 } else if (os_strcmp(buf, "dh_file") == 0) {
1554                         os_free(bss->dh_file);
1555                         bss->dh_file = os_strdup(pos);
1556                 } else if (os_strcmp(buf, "fragment_size") == 0) {
1557                         bss->fragment_size = atoi(pos);
1558 #ifdef EAP_SERVER_FAST
1559                 } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
1560                         os_free(bss->pac_opaque_encr_key);
1561                         bss->pac_opaque_encr_key = os_malloc(16);
1562                         if (bss->pac_opaque_encr_key == NULL) {
1563                                 wpa_printf(MSG_ERROR, "Line %d: No memory for "
1564                                            "pac_opaque_encr_key", line);
1565                                 errors++;
1566                         } else if (hexstr2bin(pos, bss->pac_opaque_encr_key,
1567                                               16)) {
1568                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
1569                                            "pac_opaque_encr_key", line);
1570                                 errors++;
1571                         }
1572                 } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
1573                         size_t idlen = os_strlen(pos);
1574                         if (idlen & 1) {
1575                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
1576                                            "eap_fast_a_id", line);
1577                                 errors++;
1578                         } else {
1579                                 os_free(bss->eap_fast_a_id);
1580                                 bss->eap_fast_a_id = os_malloc(idlen / 2);
1581                                 if (bss->eap_fast_a_id == NULL ||
1582                                     hexstr2bin(pos, bss->eap_fast_a_id,
1583                                                idlen / 2)) {
1584                                         wpa_printf(MSG_ERROR, "Line %d: "
1585                                                    "Failed to parse "
1586                                                    "eap_fast_a_id", line);
1587                                         errors++;
1588                                 } else
1589                                         bss->eap_fast_a_id_len = idlen / 2;
1590                         }
1591                 } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
1592                         os_free(bss->eap_fast_a_id_info);
1593                         bss->eap_fast_a_id_info = os_strdup(pos);
1594                 } else if (os_strcmp(buf, "eap_fast_prov") == 0) {
1595                         bss->eap_fast_prov = atoi(pos);
1596                 } else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
1597                         bss->pac_key_lifetime = atoi(pos);
1598                 } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
1599                         bss->pac_key_refresh_time = atoi(pos);
1600 #endif /* EAP_SERVER_FAST */
1601 #ifdef EAP_SERVER_SIM
1602                 } else if (os_strcmp(buf, "eap_sim_db") == 0) {
1603                         os_free(bss->eap_sim_db);
1604                         bss->eap_sim_db = os_strdup(pos);
1605                 } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
1606                         bss->eap_sim_aka_result_ind = atoi(pos);
1607 #endif /* EAP_SERVER_SIM */
1608 #ifdef EAP_SERVER_TNC
1609                 } else if (os_strcmp(buf, "tnc") == 0) {
1610                         bss->tnc = atoi(pos);
1611 #endif /* EAP_SERVER_TNC */
1612 #ifdef EAP_SERVER_PWD
1613                 } else if (os_strcmp(buf, "pwd_group") == 0) {
1614                         bss->pwd_group = atoi(pos);
1615 #endif /* EAP_SERVER_PWD */
1616 #endif /* EAP_SERVER */
1617                 } else if (os_strcmp(buf, "eap_message") == 0) {
1618                         char *term;
1619                         bss->eap_req_id_text = os_strdup(pos);
1620                         if (bss->eap_req_id_text == NULL) {
1621                                 wpa_printf(MSG_ERROR, "Line %d: Failed to "
1622                                            "allocate memory for "
1623                                            "eap_req_id_text", line);
1624                                 errors++;
1625                                 return errors;
1626                         }
1627                         bss->eap_req_id_text_len =
1628                                 os_strlen(bss->eap_req_id_text);
1629                         term = os_strstr(bss->eap_req_id_text, "\\0");
1630                         if (term) {
1631                                 *term++ = '\0';
1632                                 os_memmove(term, term + 1,
1633                                            bss->eap_req_id_text_len -
1634                                            (term - bss->eap_req_id_text) - 1);
1635                                 bss->eap_req_id_text_len--;
1636                         }
1637                 } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
1638                         bss->default_wep_key_len = atoi(pos);
1639                         if (bss->default_wep_key_len > 13) {
1640                                 wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
1641                                            "key len %lu (= %lu bits)", line,
1642                                            (unsigned long)
1643                                            bss->default_wep_key_len,
1644                                            (unsigned long)
1645                                            bss->default_wep_key_len * 8);
1646                                 errors++;
1647                         }
1648                 } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
1649                         bss->individual_wep_key_len = atoi(pos);
1650                         if (bss->individual_wep_key_len < 0 ||
1651                             bss->individual_wep_key_len > 13) {
1652                                 wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
1653                                            "key len %d (= %d bits)", line,
1654                                            bss->individual_wep_key_len,
1655                                            bss->individual_wep_key_len * 8);
1656                                 errors++;
1657                         }
1658                 } else if (os_strcmp(buf, "wep_rekey_period") == 0) {
1659                         bss->wep_rekeying_period = atoi(pos);
1660                         if (bss->wep_rekeying_period < 0) {
1661                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
1662                                            "period %d",
1663                                            line, bss->wep_rekeying_period);
1664                                 errors++;
1665                         }
1666                 } else if (os_strcmp(buf, "eap_reauth_period") == 0) {
1667                         bss->eap_reauth_period = atoi(pos);
1668                         if (bss->eap_reauth_period < 0) {
1669                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
1670                                            "period %d",
1671                                            line, bss->eap_reauth_period);
1672                                 errors++;
1673                         }
1674                 } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
1675                         bss->eapol_key_index_workaround = atoi(pos);
1676 #ifdef CONFIG_IAPP
1677                 } else if (os_strcmp(buf, "iapp_interface") == 0) {
1678                         bss->ieee802_11f = 1;
1679                         os_strlcpy(bss->iapp_iface, pos,
1680                                    sizeof(bss->iapp_iface));
1681 #endif /* CONFIG_IAPP */
1682                 } else if (os_strcmp(buf, "own_ip_addr") == 0) {
1683                         if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
1684                                 wpa_printf(MSG_ERROR, "Line %d: invalid IP "
1685                                            "address '%s'", line, pos);
1686                                 errors++;
1687                         }
1688                 } else if (os_strcmp(buf, "nas_identifier") == 0) {
1689                         bss->nas_identifier = os_strdup(pos);
1690 #ifndef CONFIG_NO_RADIUS
1691                 } else if (os_strcmp(buf, "auth_server_addr") == 0) {
1692                         if (hostapd_config_read_radius_addr(
1693                                     &bss->radius->auth_servers,
1694                                     &bss->radius->num_auth_servers, pos, 1812,
1695                                     &bss->radius->auth_server)) {
1696                                 wpa_printf(MSG_ERROR, "Line %d: invalid IP "
1697                                            "address '%s'", line, pos);
1698                                 errors++;
1699                         }
1700                 } else if (bss->radius->auth_server &&
1701                            os_strcmp(buf, "auth_server_port") == 0) {
1702                         bss->radius->auth_server->port = atoi(pos);
1703                 } else if (bss->radius->auth_server &&
1704                            os_strcmp(buf, "auth_server_shared_secret") == 0) {
1705                         int len = os_strlen(pos);
1706                         if (len == 0) {
1707                                 /* RFC 2865, Ch. 3 */
1708                                 wpa_printf(MSG_ERROR, "Line %d: empty shared "
1709                                            "secret is not allowed.", line);
1710                                 errors++;
1711                         }
1712                         bss->radius->auth_server->shared_secret =
1713                                 (u8 *) os_strdup(pos);
1714                         bss->radius->auth_server->shared_secret_len = len;
1715                 } else if (os_strcmp(buf, "acct_server_addr") == 0) {
1716                         if (hostapd_config_read_radius_addr(
1717                                     &bss->radius->acct_servers,
1718                                     &bss->radius->num_acct_servers, pos, 1813,
1719                                     &bss->radius->acct_server)) {
1720                                 wpa_printf(MSG_ERROR, "Line %d: invalid IP "
1721                                            "address '%s'", line, pos);
1722                                 errors++;
1723                         }
1724                 } else if (bss->radius->acct_server &&
1725                            os_strcmp(buf, "acct_server_port") == 0) {
1726                         bss->radius->acct_server->port = atoi(pos);
1727                 } else if (bss->radius->acct_server &&
1728                            os_strcmp(buf, "acct_server_shared_secret") == 0) {
1729                         int len = os_strlen(pos);
1730                         if (len == 0) {
1731                                 /* RFC 2865, Ch. 3 */
1732                                 wpa_printf(MSG_ERROR, "Line %d: empty shared "
1733                                            "secret is not allowed.", line);
1734                                 errors++;
1735                         }
1736                         bss->radius->acct_server->shared_secret =
1737                                 (u8 *) os_strdup(pos);
1738                         bss->radius->acct_server->shared_secret_len = len;
1739                 } else if (os_strcmp(buf, "radius_retry_primary_interval") ==
1740                            0) {
1741                         bss->radius->retry_primary_interval = atoi(pos);
1742                 } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0)
1743                 {
1744                         bss->acct_interim_interval = atoi(pos);
1745                 } else if (os_strcmp(buf, "radius_request_cui") == 0) {
1746                         bss->radius_request_cui = atoi(pos);
1747                 } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
1748                         struct hostapd_radius_attr *attr, *a;
1749                         attr = hostapd_parse_radius_attr(pos);
1750                         if (attr == NULL) {
1751                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
1752                                            "radius_auth_req_attr", line);
1753                                 errors++;
1754                         } else if (bss->radius_auth_req_attr == NULL) {
1755                                 bss->radius_auth_req_attr = attr;
1756                         } else {
1757                                 a = bss->radius_auth_req_attr;
1758                                 while (a->next)
1759                                         a = a->next;
1760                                 a->next = attr;
1761                         }
1762                 } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
1763                         struct hostapd_radius_attr *attr, *a;
1764                         attr = hostapd_parse_radius_attr(pos);
1765                         if (attr == NULL) {
1766                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
1767                                            "radius_acct_req_attr", line);
1768                                 errors++;
1769                         } else if (bss->radius_acct_req_attr == NULL) {
1770                                 bss->radius_acct_req_attr = attr;
1771                         } else {
1772                                 a = bss->radius_acct_req_attr;
1773                                 while (a->next)
1774                                         a = a->next;
1775                                 a->next = attr;
1776                         }
1777                 } else if (os_strcmp(buf, "radius_das_port") == 0) {
1778                         bss->radius_das_port = atoi(pos);
1779                 } else if (os_strcmp(buf, "radius_das_client") == 0) {
1780                         if (hostapd_parse_das_client(bss, pos) < 0) {
1781                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
1782                                            "DAS client", line);
1783                                 errors++;
1784                         }
1785                 } else if (os_strcmp(buf, "radius_das_time_window") == 0) {
1786                         bss->radius_das_time_window = atoi(pos);
1787                 } else if (os_strcmp(buf, "radius_das_require_event_timestamp")
1788                            == 0) {
1789                         bss->radius_das_require_event_timestamp = atoi(pos);
1790 #endif /* CONFIG_NO_RADIUS */
1791                 } else if (os_strcmp(buf, "auth_algs") == 0) {
1792                         bss->auth_algs = atoi(pos);
1793                         if (bss->auth_algs == 0) {
1794                                 wpa_printf(MSG_ERROR, "Line %d: no "
1795                                            "authentication algorithms allowed",
1796                                            line);
1797                                 errors++;
1798                         }
1799                 } else if (os_strcmp(buf, "max_num_sta") == 0) {
1800                         bss->max_num_sta = atoi(pos);
1801                         if (bss->max_num_sta < 0 ||
1802                             bss->max_num_sta > MAX_STA_COUNT) {
1803                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
1804                                            "max_num_sta=%d; allowed range "
1805                                            "0..%d", line, bss->max_num_sta,
1806                                            MAX_STA_COUNT);
1807                                 errors++;
1808                         }
1809                 } else if (os_strcmp(buf, "wpa") == 0) {
1810                         bss->wpa = atoi(pos);
1811                 } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
1812                         bss->wpa_group_rekey = atoi(pos);
1813                 } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
1814                         bss->wpa_strict_rekey = atoi(pos);
1815                 } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
1816                         bss->wpa_gmk_rekey = atoi(pos);
1817                 } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
1818                         bss->wpa_ptk_rekey = atoi(pos);
1819                 } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
1820                         int len = os_strlen(pos);
1821                         if (len < 8 || len > 63) {
1822                                 wpa_printf(MSG_ERROR, "Line %d: invalid WPA "
1823                                            "passphrase length %d (expected "
1824                                            "8..63)", line, len);
1825                                 errors++;
1826                         } else {
1827                                 os_free(bss->ssid.wpa_passphrase);
1828                                 bss->ssid.wpa_passphrase = os_strdup(pos);
1829                                 os_free(bss->ssid.wpa_psk);
1830                                 bss->ssid.wpa_psk = NULL;
1831                         }
1832                 } else if (os_strcmp(buf, "wpa_psk") == 0) {
1833                         os_free(bss->ssid.wpa_psk);
1834                         bss->ssid.wpa_psk =
1835                                 os_zalloc(sizeof(struct hostapd_wpa_psk));
1836                         if (bss->ssid.wpa_psk == NULL)
1837                                 errors++;
1838                         else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk,
1839                                             PMK_LEN) ||
1840                                  pos[PMK_LEN * 2] != '\0') {
1841                                 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK "
1842                                            "'%s'.", line, pos);
1843                                 errors++;
1844                         } else {
1845                                 bss->ssid.wpa_psk->group = 1;
1846                                 os_free(bss->ssid.wpa_passphrase);
1847                                 bss->ssid.wpa_passphrase = NULL;
1848                         }
1849                 } else if (os_strcmp(buf, "wpa_psk_file") == 0) {
1850                         os_free(bss->ssid.wpa_psk_file);
1851                         bss->ssid.wpa_psk_file = os_strdup(pos);
1852                         if (!bss->ssid.wpa_psk_file) {
1853                                 wpa_printf(MSG_ERROR, "Line %d: allocation "
1854                                            "failed", line);
1855                                 errors++;
1856                         }
1857                 } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
1858                         bss->wpa_key_mgmt =
1859                                 hostapd_config_parse_key_mgmt(line, pos);
1860                         if (bss->wpa_key_mgmt == -1)
1861                                 errors++;
1862                 } else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
1863                         bss->wpa_psk_radius = atoi(pos);
1864                         if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
1865                             bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
1866                             bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
1867                                 wpa_printf(MSG_ERROR, "Line %d: unknown "
1868                                            "wpa_psk_radius %d",
1869                                            line, bss->wpa_psk_radius);
1870                                 errors++;
1871                         }
1872                 } else if (os_strcmp(buf, "wpa_pairwise") == 0) {
1873                         bss->wpa_pairwise =
1874                                 hostapd_config_parse_cipher(line, pos);
1875                         if (bss->wpa_pairwise == -1 ||
1876                             bss->wpa_pairwise == 0)
1877                                 errors++;
1878                         else if (bss->wpa_pairwise &
1879                                  (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
1880                                   WPA_CIPHER_WEP104)) {
1881                                 wpa_printf(MSG_ERROR, "Line %d: unsupported "
1882                                            "pairwise cipher suite '%s'",
1883                                            bss->wpa_pairwise, pos);
1884                                 errors++;
1885                         }
1886                 } else if (os_strcmp(buf, "rsn_pairwise") == 0) {
1887                         bss->rsn_pairwise =
1888                                 hostapd_config_parse_cipher(line, pos);
1889                         if (bss->rsn_pairwise == -1 ||
1890                             bss->rsn_pairwise == 0)
1891                                 errors++;
1892                         else if (bss->rsn_pairwise &
1893                                  (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
1894                                   WPA_CIPHER_WEP104)) {
1895                                 wpa_printf(MSG_ERROR, "Line %d: unsupported "
1896                                            "pairwise cipher suite '%s'",
1897                                            bss->rsn_pairwise, pos);
1898                                 errors++;
1899                         }
1900 #ifdef CONFIG_RSN_PREAUTH
1901                 } else if (os_strcmp(buf, "rsn_preauth") == 0) {
1902                         bss->rsn_preauth = atoi(pos);
1903                 } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
1904                         bss->rsn_preauth_interfaces = os_strdup(pos);
1905 #endif /* CONFIG_RSN_PREAUTH */
1906 #ifdef CONFIG_PEERKEY
1907                 } else if (os_strcmp(buf, "peerkey") == 0) {
1908                         bss->peerkey = atoi(pos);
1909 #endif /* CONFIG_PEERKEY */
1910 #ifdef CONFIG_IEEE80211R
1911                 } else if (os_strcmp(buf, "mobility_domain") == 0) {
1912                         if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
1913                             hexstr2bin(pos, bss->mobility_domain,
1914                                        MOBILITY_DOMAIN_ID_LEN) != 0) {
1915                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1916                                            "mobility_domain '%s'", line, pos);
1917                                 errors++;
1918                                 return errors;
1919                         }
1920                 } else if (os_strcmp(buf, "r1_key_holder") == 0) {
1921                         if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
1922                             hexstr2bin(pos, bss->r1_key_holder,
1923                                        FT_R1KH_ID_LEN) != 0) {
1924                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1925                                            "r1_key_holder '%s'", line, pos);
1926                                 errors++;
1927                                 return errors;
1928                         }
1929                 } else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
1930                         bss->r0_key_lifetime = atoi(pos);
1931                 } else if (os_strcmp(buf, "reassociation_deadline") == 0) {
1932                         bss->reassociation_deadline = atoi(pos);
1933                 } else if (os_strcmp(buf, "r0kh") == 0) {
1934                         if (add_r0kh(bss, pos) < 0) {
1935                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1936                                            "r0kh '%s'", line, pos);
1937                                 errors++;
1938                                 return errors;
1939                         }
1940                 } else if (os_strcmp(buf, "r1kh") == 0) {
1941                         if (add_r1kh(bss, pos) < 0) {
1942                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1943                                            "r1kh '%s'", line, pos);
1944                                 errors++;
1945                                 return errors;
1946                         }
1947                 } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
1948                         bss->pmk_r1_push = atoi(pos);
1949                 } else if (os_strcmp(buf, "ft_over_ds") == 0) {
1950                         bss->ft_over_ds = atoi(pos);
1951 #endif /* CONFIG_IEEE80211R */
1952 #ifndef CONFIG_NO_CTRL_IFACE
1953                 } else if (os_strcmp(buf, "ctrl_interface") == 0) {
1954                         os_free(bss->ctrl_interface);
1955                         bss->ctrl_interface = os_strdup(pos);
1956                 } else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
1957 #ifndef CONFIG_NATIVE_WINDOWS
1958                         struct group *grp;
1959                         char *endp;
1960                         const char *group = pos;
1961
1962                         grp = getgrnam(group);
1963                         if (grp) {
1964                                 bss->ctrl_interface_gid = grp->gr_gid;
1965                                 bss->ctrl_interface_gid_set = 1;
1966                                 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
1967                                            " (from group name '%s')",
1968                                            bss->ctrl_interface_gid, group);
1969                                 return errors;
1970                         }
1971
1972                         /* Group name not found - try to parse this as gid */
1973                         bss->ctrl_interface_gid = strtol(group, &endp, 10);
1974                         if (*group == '\0' || *endp != '\0') {
1975                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
1976                                            "'%s'", line, group);
1977                                 errors++;
1978                                 return errors;
1979                         }
1980                         bss->ctrl_interface_gid_set = 1;
1981                         wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
1982                                    bss->ctrl_interface_gid);
1983 #endif /* CONFIG_NATIVE_WINDOWS */
1984 #endif /* CONFIG_NO_CTRL_IFACE */
1985 #ifdef RADIUS_SERVER
1986                 } else if (os_strcmp(buf, "radius_server_clients") == 0) {
1987                         os_free(bss->radius_server_clients);
1988                         bss->radius_server_clients = os_strdup(pos);
1989                 } else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
1990                         bss->radius_server_auth_port = atoi(pos);
1991                 } else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
1992                         bss->radius_server_ipv6 = atoi(pos);
1993 #endif /* RADIUS_SERVER */
1994                 } else if (os_strcmp(buf, "test_socket") == 0) {
1995                         os_free(bss->test_socket);
1996                         bss->test_socket = os_strdup(pos);
1997                 } else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
1998                         bss->use_pae_group_addr = atoi(pos);
1999                 } else if (os_strcmp(buf, "hw_mode") == 0) {
2000                         if (os_strcmp(pos, "a") == 0)
2001                                 conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
2002                         else if (os_strcmp(pos, "b") == 0)
2003                                 conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
2004                         else if (os_strcmp(pos, "g") == 0)
2005                                 conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
2006                         else {
2007                                 wpa_printf(MSG_ERROR, "Line %d: unknown "
2008                                            "hw_mode '%s'", line, pos);
2009                                 errors++;
2010                         }
2011                 } else if (os_strcmp(buf, "wps_rf_bands") == 0) {
2012                         if (os_strcmp(pos, "a") == 0)
2013                                 bss->wps_rf_bands = WPS_RF_50GHZ;
2014                         else if (os_strcmp(pos, "g") == 0 ||
2015                                  os_strcmp(pos, "b") == 0)
2016                                 bss->wps_rf_bands = WPS_RF_24GHZ;
2017                         else if (os_strcmp(pos, "ag") == 0 ||
2018                                  os_strcmp(pos, "ga") == 0)
2019                                 bss->wps_rf_bands =
2020                                         WPS_RF_24GHZ | WPS_RF_50GHZ;
2021                         else {
2022                                 wpa_printf(MSG_ERROR, "Line %d: unknown "
2023                                            "wps_rf_band '%s'", line, pos);
2024                                 errors++;
2025                         }
2026                 } else if (os_strcmp(buf, "channel") == 0) {
2027                         conf->channel = atoi(pos);
2028                 } else if (os_strcmp(buf, "beacon_int") == 0) {
2029                         int val = atoi(pos);
2030                         /* MIB defines range as 1..65535, but very small values
2031                          * cause problems with the current implementation.
2032                          * Since it is unlikely that this small numbers are
2033                          * useful in real life scenarios, do not allow beacon
2034                          * period to be set below 15 TU. */
2035                         if (val < 15 || val > 65535) {
2036                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2037                                            "beacon_int %d (expected "
2038                                            "15..65535)", line, val);
2039                                 errors++;
2040                         } else
2041                                 conf->beacon_int = val;
2042                 } else if (os_strcmp(buf, "dtim_period") == 0) {
2043                         bss->dtim_period = atoi(pos);
2044                         if (bss->dtim_period < 1 || bss->dtim_period > 255) {
2045                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2046                                            "dtim_period %d",
2047                                            line, bss->dtim_period);
2048                                 errors++;
2049                         }
2050                 } else if (os_strcmp(buf, "rts_threshold") == 0) {
2051                         conf->rts_threshold = atoi(pos);
2052                         if (conf->rts_threshold < 0 ||
2053                             conf->rts_threshold > 2347) {
2054                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2055                                            "rts_threshold %d",
2056                                            line, conf->rts_threshold);
2057                                 errors++;
2058                         }
2059                 } else if (os_strcmp(buf, "fragm_threshold") == 0) {
2060                         conf->fragm_threshold = atoi(pos);
2061                         if (conf->fragm_threshold < 256 ||
2062                             conf->fragm_threshold > 2346) {
2063                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2064                                            "fragm_threshold %d",
2065                                            line, conf->fragm_threshold);
2066                                 errors++;
2067                         }
2068                 } else if (os_strcmp(buf, "send_probe_response") == 0) {
2069                         int val = atoi(pos);
2070                         if (val != 0 && val != 1) {
2071                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2072                                            "send_probe_response %d (expected "
2073                                            "0 or 1)", line, val);
2074                         } else
2075                                 conf->send_probe_response = val;
2076                 } else if (os_strcmp(buf, "supported_rates") == 0) {
2077                         if (hostapd_parse_rates(&conf->supported_rates, pos)) {
2078                                 wpa_printf(MSG_ERROR, "Line %d: invalid rate "
2079                                            "list", line);
2080                                 errors++;
2081                         }
2082                 } else if (os_strcmp(buf, "basic_rates") == 0) {
2083                         if (hostapd_parse_rates(&conf->basic_rates, pos)) {
2084                                 wpa_printf(MSG_ERROR, "Line %d: invalid rate "
2085                                            "list", line);
2086                                 errors++;
2087                         }
2088                 } else if (os_strcmp(buf, "preamble") == 0) {
2089                         if (atoi(pos))
2090                                 conf->preamble = SHORT_PREAMBLE;
2091                         else
2092                                 conf->preamble = LONG_PREAMBLE;
2093                 } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
2094                         bss->ignore_broadcast_ssid = atoi(pos);
2095                 } else if (os_strcmp(buf, "wep_default_key") == 0) {
2096                         bss->ssid.wep.idx = atoi(pos);
2097                         if (bss->ssid.wep.idx > 3) {
2098                                 wpa_printf(MSG_ERROR, "Invalid "
2099                                            "wep_default_key index %d",
2100                                            bss->ssid.wep.idx);
2101                                 errors++;
2102                         }
2103                 } else if (os_strcmp(buf, "wep_key0") == 0 ||
2104                            os_strcmp(buf, "wep_key1") == 0 ||
2105                            os_strcmp(buf, "wep_key2") == 0 ||
2106                            os_strcmp(buf, "wep_key3") == 0) {
2107                         if (hostapd_config_read_wep(&bss->ssid.wep,
2108                                                     buf[7] - '0', pos)) {
2109                                 wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
2110                                            "key '%s'", line, buf);
2111                                 errors++;
2112                         }
2113 #ifndef CONFIG_NO_VLAN
2114                 } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
2115                         bss->ssid.dynamic_vlan = atoi(pos);
2116                 } else if (os_strcmp(buf, "vlan_file") == 0) {
2117                         if (hostapd_config_read_vlan_file(bss, pos)) {
2118                                 wpa_printf(MSG_ERROR, "Line %d: failed to "
2119                                            "read VLAN file '%s'", line, pos);
2120                                 errors++;
2121                         }
2122 #ifdef CONFIG_FULL_DYNAMIC_VLAN
2123                 } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
2124                         bss->ssid.vlan_tagged_interface = os_strdup(pos);
2125 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
2126 #endif /* CONFIG_NO_VLAN */
2127                 } else if (os_strcmp(buf, "ap_table_max_size") == 0) {
2128                         conf->ap_table_max_size = atoi(pos);
2129                 } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
2130                         conf->ap_table_expiration_time = atoi(pos);
2131                 } else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
2132                         if (hostapd_config_tx_queue(conf, buf, pos)) {
2133                                 wpa_printf(MSG_ERROR, "Line %d: invalid TX "
2134                                            "queue item", line);
2135                                 errors++;
2136                         }
2137                 } else if (os_strcmp(buf, "wme_enabled") == 0 ||
2138                            os_strcmp(buf, "wmm_enabled") == 0) {
2139                         bss->wmm_enabled = atoi(pos);
2140                 } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
2141                         bss->wmm_uapsd = atoi(pos);
2142                 } else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
2143                            os_strncmp(buf, "wmm_ac_", 7) == 0) {
2144                         if (hostapd_config_wmm_ac(conf, buf, pos)) {
2145                                 wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
2146                                            "ac item", line);
2147                                 errors++;
2148                         }
2149                 } else if (os_strcmp(buf, "bss") == 0) {
2150                         if (hostapd_config_bss(conf, pos)) {
2151                                 wpa_printf(MSG_ERROR, "Line %d: invalid bss "
2152                                            "item", line);
2153                                 errors++;
2154                         }
2155                 } else if (os_strcmp(buf, "bssid") == 0) {
2156                         if (hwaddr_aton(pos, bss->bssid)) {
2157                                 wpa_printf(MSG_ERROR, "Line %d: invalid bssid "
2158                                            "item", line);
2159                                 errors++;
2160                         }
2161 #ifdef CONFIG_IEEE80211W
2162                 } else if (os_strcmp(buf, "ieee80211w") == 0) {
2163                         bss->ieee80211w = atoi(pos);
2164                 } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
2165                         bss->assoc_sa_query_max_timeout = atoi(pos);
2166                         if (bss->assoc_sa_query_max_timeout == 0) {
2167                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2168                                            "assoc_sa_query_max_timeout", line);
2169                                 errors++;
2170                         }
2171                 } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0)
2172                 {
2173                         bss->assoc_sa_query_retry_timeout = atoi(pos);
2174                         if (bss->assoc_sa_query_retry_timeout == 0) {
2175                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2176                                            "assoc_sa_query_retry_timeout",
2177                                            line);
2178                                 errors++;
2179                         }
2180 #endif /* CONFIG_IEEE80211W */
2181 #ifdef CONFIG_IEEE80211N
2182                 } else if (os_strcmp(buf, "ieee80211n") == 0) {
2183                         conf->ieee80211n = atoi(pos);
2184                 } else if (os_strcmp(buf, "ht_capab") == 0) {
2185                         if (hostapd_config_ht_capab(conf, pos) < 0) {
2186                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2187                                            "ht_capab", line);
2188                                 errors++;
2189                         }
2190                 } else if (os_strcmp(buf, "require_ht") == 0) {
2191                         conf->require_ht = atoi(pos);
2192 #endif /* CONFIG_IEEE80211N */
2193 #ifdef CONFIG_IEEE80211AC
2194                 } else if (os_strcmp(buf, "ieee80211ac") == 0) {
2195                         conf->ieee80211ac = atoi(pos);
2196                 } else if (os_strcmp(buf, "vht_capab") == 0) {
2197                         if (hostapd_config_vht_capab(conf, pos) < 0) {
2198                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2199                                            "vht_capab", line);
2200                                 errors++;
2201                         }
2202                 } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
2203                     conf->vht_oper_chwidth = atoi(pos);
2204 #endif /* CONFIG_IEEE80211AC */
2205                 } else if (os_strcmp(buf, "max_listen_interval") == 0) {
2206                         bss->max_listen_interval = atoi(pos);
2207                 } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
2208                         bss->disable_pmksa_caching = atoi(pos);
2209                 } else if (os_strcmp(buf, "okc") == 0) {
2210                         bss->okc = atoi(pos);
2211 #ifdef CONFIG_WPS
2212                 } else if (os_strcmp(buf, "wps_state") == 0) {
2213                         bss->wps_state = atoi(pos);
2214                         if (bss->wps_state < 0 || bss->wps_state > 2) {
2215                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2216                                            "wps_state", line);
2217                                 errors++;
2218                         }
2219                 } else if (os_strcmp(buf, "ap_setup_locked") == 0) {
2220                         bss->ap_setup_locked = atoi(pos);
2221                 } else if (os_strcmp(buf, "uuid") == 0) {
2222                         if (uuid_str2bin(pos, bss->uuid)) {
2223                                 wpa_printf(MSG_ERROR, "Line %d: invalid UUID",
2224                                            line);
2225                                 errors++;
2226                         }
2227                 } else if (os_strcmp(buf, "wps_pin_requests") == 0) {
2228                         os_free(bss->wps_pin_requests);
2229                         bss->wps_pin_requests = os_strdup(pos);
2230                 } else if (os_strcmp(buf, "device_name") == 0) {
2231                         if (os_strlen(pos) > 32) {
2232                                 wpa_printf(MSG_ERROR, "Line %d: Too long "
2233                                            "device_name", line);
2234                                 errors++;
2235                         }
2236                         os_free(bss->device_name);
2237                         bss->device_name = os_strdup(pos);
2238                 } else if (os_strcmp(buf, "manufacturer") == 0) {
2239                         if (os_strlen(pos) > 64) {
2240                                 wpa_printf(MSG_ERROR, "Line %d: Too long "
2241                                            "manufacturer", line);
2242                                 errors++;
2243                         }
2244                         os_free(bss->manufacturer);
2245                         bss->manufacturer = os_strdup(pos);
2246                 } else if (os_strcmp(buf, "model_name") == 0) {
2247                         if (os_strlen(pos) > 32) {
2248                                 wpa_printf(MSG_ERROR, "Line %d: Too long "
2249                                            "model_name", line);
2250                                 errors++;
2251                         }
2252                         os_free(bss->model_name);
2253                         bss->model_name = os_strdup(pos);
2254                 } else if (os_strcmp(buf, "model_number") == 0) {
2255                         if (os_strlen(pos) > 32) {
2256                                 wpa_printf(MSG_ERROR, "Line %d: Too long "
2257                                            "model_number", line);
2258                                 errors++;
2259                         }
2260                         os_free(bss->model_number);
2261                         bss->model_number = os_strdup(pos);
2262                 } else if (os_strcmp(buf, "serial_number") == 0) {
2263                         if (os_strlen(pos) > 32) {
2264                                 wpa_printf(MSG_ERROR, "Line %d: Too long "
2265                                            "serial_number", line);
2266                                 errors++;
2267                         }
2268                         os_free(bss->serial_number);
2269                         bss->serial_number = os_strdup(pos);
2270                 } else if (os_strcmp(buf, "device_type") == 0) {
2271                         if (wps_dev_type_str2bin(pos, bss->device_type))
2272                                 errors++;
2273                 } else if (os_strcmp(buf, "config_methods") == 0) {
2274                         os_free(bss->config_methods);
2275                         bss->config_methods = os_strdup(pos);
2276                 } else if (os_strcmp(buf, "os_version") == 0) {
2277                         if (hexstr2bin(pos, bss->os_version, 4)) {
2278                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2279                                            "os_version", line);
2280                                 errors++;
2281                         }
2282                 } else if (os_strcmp(buf, "ap_pin") == 0) {
2283                         os_free(bss->ap_pin);
2284                         bss->ap_pin = os_strdup(pos);
2285                 } else if (os_strcmp(buf, "skip_cred_build") == 0) {
2286                         bss->skip_cred_build = atoi(pos);
2287                 } else if (os_strcmp(buf, "extra_cred") == 0) {
2288                         os_free(bss->extra_cred);
2289                         bss->extra_cred =
2290                                 (u8 *) os_readfile(pos, &bss->extra_cred_len);
2291                         if (bss->extra_cred == NULL) {
2292                                 wpa_printf(MSG_ERROR, "Line %d: could not "
2293                                            "read Credentials from '%s'",
2294                                            line, pos);
2295                                 errors++;
2296                         }
2297                 } else if (os_strcmp(buf, "wps_cred_processing") == 0) {
2298                         bss->wps_cred_processing = atoi(pos);
2299                 } else if (os_strcmp(buf, "ap_settings") == 0) {
2300                         os_free(bss->ap_settings);
2301                         bss->ap_settings =
2302                                 (u8 *) os_readfile(pos, &bss->ap_settings_len);
2303                         if (bss->ap_settings == NULL) {
2304                                 wpa_printf(MSG_ERROR, "Line %d: could not "
2305                                            "read AP Settings from '%s'",
2306                                            line, pos);
2307                                 errors++;
2308                         }
2309                 } else if (os_strcmp(buf, "upnp_iface") == 0) {
2310                         bss->upnp_iface = os_strdup(pos);
2311                 } else if (os_strcmp(buf, "friendly_name") == 0) {
2312                         os_free(bss->friendly_name);
2313                         bss->friendly_name = os_strdup(pos);
2314                 } else if (os_strcmp(buf, "manufacturer_url") == 0) {
2315                         os_free(bss->manufacturer_url);
2316                         bss->manufacturer_url = os_strdup(pos);
2317                 } else if (os_strcmp(buf, "model_description") == 0) {
2318                         os_free(bss->model_description);
2319                         bss->model_description = os_strdup(pos);
2320                 } else if (os_strcmp(buf, "model_url") == 0) {
2321                         os_free(bss->model_url);
2322                         bss->model_url = os_strdup(pos);
2323                 } else if (os_strcmp(buf, "upc") == 0) {
2324                         os_free(bss->upc);
2325                         bss->upc = os_strdup(pos);
2326                 } else if (os_strcmp(buf, "pbc_in_m1") == 0) {
2327                         bss->pbc_in_m1 = atoi(pos);
2328 #ifdef CONFIG_WPS_NFC
2329                 } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
2330                         bss->wps_nfc_dev_pw_id = atoi(pos);
2331                         if (bss->wps_nfc_dev_pw_id < 0x10 ||
2332                             bss->wps_nfc_dev_pw_id > 0xffff) {
2333                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
2334                                            "wps_nfc_dev_pw_id value", line);
2335                                 errors++;
2336                         }
2337                 } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
2338                         wpabuf_free(bss->wps_nfc_dh_pubkey);
2339                         bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos);
2340                 } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
2341                         wpabuf_free(bss->wps_nfc_dh_privkey);
2342                         bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos);
2343                 } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
2344                         wpabuf_free(bss->wps_nfc_dev_pw);
2345                         bss->wps_nfc_dev_pw = hostapd_parse_bin(pos);
2346 #endif /* CONFIG_WPS_NFC */
2347 #endif /* CONFIG_WPS */
2348 #ifdef CONFIG_P2P_MANAGER
2349                 } else if (os_strcmp(buf, "manage_p2p") == 0) {
2350                         int manage = atoi(pos);
2351                         if (manage)
2352                                 bss->p2p |= P2P_MANAGE;
2353                         else
2354                                 bss->p2p &= ~P2P_MANAGE;
2355                 } else if (os_strcmp(buf, "allow_cross_connection") == 0) {
2356                         if (atoi(pos))
2357                                 bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
2358                         else
2359                                 bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
2360 #endif /* CONFIG_P2P_MANAGER */
2361                 } else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
2362                         bss->disassoc_low_ack = atoi(pos);
2363                 } else if (os_strcmp(buf, "tdls_prohibit") == 0) {
2364                         int val = atoi(pos);
2365                         if (val)
2366                                 bss->tdls |= TDLS_PROHIBIT;
2367                         else
2368                                 bss->tdls &= ~TDLS_PROHIBIT;
2369                 } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
2370                         int val = atoi(pos);
2371                         if (val)
2372                                 bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
2373                         else
2374                                 bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
2375 #ifdef CONFIG_RSN_TESTING
2376                 } else if (os_strcmp(buf, "rsn_testing") == 0) {
2377                         extern int rsn_testing;
2378                         rsn_testing = atoi(pos);
2379 #endif /* CONFIG_RSN_TESTING */
2380                 } else if (os_strcmp(buf, "time_advertisement") == 0) {
2381                         bss->time_advertisement = atoi(pos);
2382                 } else if (os_strcmp(buf, "time_zone") == 0) {
2383                         size_t tz_len = os_strlen(pos);
2384                         if (tz_len < 4 || tz_len > 255) {
2385                                 wpa_printf(MSG_DEBUG, "Line %d: invalid "
2386                                            "time_zone", line);
2387                                 errors++;
2388                                 return errors;
2389                         }
2390                         os_free(bss->time_zone);
2391                         bss->time_zone = os_strdup(pos);
2392                         if (bss->time_zone == NULL)
2393                                 errors++;
2394 #ifdef CONFIG_INTERWORKING
2395                 } else if (os_strcmp(buf, "interworking") == 0) {
2396                         bss->interworking = atoi(pos);
2397                 } else if (os_strcmp(buf, "access_network_type") == 0) {
2398                         bss->access_network_type = atoi(pos);
2399                         if (bss->access_network_type < 0 ||
2400                             bss->access_network_type > 15) {
2401                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2402                                            "access_network_type", line);
2403                                 errors++;
2404                         }
2405                 } else if (os_strcmp(buf, "internet") == 0) {
2406                         bss->internet = atoi(pos);
2407                 } else if (os_strcmp(buf, "asra") == 0) {
2408                         bss->asra = atoi(pos);
2409                 } else if (os_strcmp(buf, "esr") == 0) {
2410                         bss->esr = atoi(pos);
2411                 } else if (os_strcmp(buf, "uesa") == 0) {
2412                         bss->uesa = atoi(pos);
2413                 } else if (os_strcmp(buf, "venue_group") == 0) {
2414                         bss->venue_group = atoi(pos);
2415                         bss->venue_info_set = 1;
2416                 } else if (os_strcmp(buf, "venue_type") == 0) {
2417                         bss->venue_type = atoi(pos);
2418                         bss->venue_info_set = 1;
2419                 } else if (os_strcmp(buf, "hessid") == 0) {
2420                         if (hwaddr_aton(pos, bss->hessid)) {
2421                                 wpa_printf(MSG_ERROR, "Line %d: invalid "
2422                                            "hessid", line);
2423                                 errors++;
2424                         }
2425                 } else if (os_strcmp(buf, "roaming_consortium") == 0) {
2426                         if (parse_roaming_consortium(bss, pos, line) < 0)
2427                                 errors++;
2428                 } else if (os_strcmp(buf, "venue_name") == 0) {
2429                         if (parse_venue_name(bss, pos, line) < 0)
2430                                 errors++;
2431                 } else if (os_strcmp(buf, "network_auth_type") == 0) {
2432                         u8 auth_type;
2433                         u16 redirect_url_len;
2434                         if (hexstr2bin(pos, &auth_type, 1)) {
2435                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
2436                                            "network_auth_type '%s'",
2437                                            line, pos);
2438                                 errors++;
2439                                 return errors;
2440                         }
2441                         if (auth_type == 0 || auth_type == 2)
2442                                 redirect_url_len = os_strlen(pos + 2);
2443                         else
2444                                 redirect_url_len = 0;
2445                         os_free(bss->network_auth_type);
2446                         bss->network_auth_type =
2447                                 os_malloc(redirect_url_len + 3 + 1);
2448                         if (bss->network_auth_type == NULL) {
2449                                 errors++;
2450                                 return errors;
2451                         }
2452                         *bss->network_auth_type = auth_type;
2453                         WPA_PUT_LE16(bss->network_auth_type + 1,
2454                                      redirect_url_len);
2455                         if (redirect_url_len)
2456                                 os_memcpy(bss->network_auth_type + 3,
2457                                           pos + 2, redirect_url_len);
2458                         bss->network_auth_type_len = 3 + redirect_url_len;
2459                 } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
2460                         if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1))
2461                         {
2462                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
2463                                            "ipaddr_type_availability '%s'",
2464                                            line, pos);
2465                                 bss->ipaddr_type_configured = 0;
2466                                 errors++;
2467                                 return errors;
2468                         }
2469                         bss->ipaddr_type_configured = 1;
2470                 } else if (os_strcmp(buf, "domain_name") == 0) {
2471                         int j, num_domains, domain_len, domain_list_len = 0;
2472                         char *tok_start, *tok_prev;
2473                         u8 *domain_list, *domain_ptr;
2474
2475                         domain_list_len = os_strlen(pos) + 1;
2476                         domain_list = os_malloc(domain_list_len);
2477                         if (domain_list == NULL) {
2478                                 errors++;
2479                                 return errors;
2480                         }
2481
2482                         domain_ptr = domain_list;
2483                         tok_prev = pos;
2484                         num_domains = 1;
2485                         while ((tok_prev = os_strchr(tok_prev, ','))) {
2486                                 num_domains++;
2487                                 tok_prev++;
2488                         }
2489                         tok_prev = pos;
2490                         for (j = 0; j < num_domains; j++) {
2491                                 tok_start = os_strchr(tok_prev, ',');
2492                                 if (tok_start) {
2493                                         domain_len = tok_start - tok_prev;
2494                                         *domain_ptr = domain_len;
2495                                         os_memcpy(domain_ptr + 1, tok_prev,
2496                                                   domain_len);
2497                                         domain_ptr += domain_len + 1;
2498                                         tok_prev = ++tok_start;
2499                                 } else {
2500                                         domain_len = os_strlen(tok_prev);
2501                                         *domain_ptr = domain_len;
2502                                         os_memcpy(domain_ptr + 1, tok_prev,
2503                                                   domain_len);
2504                                         domain_ptr += domain_len + 1;
2505                                 }
2506                         }
2507
2508                         os_free(bss->domain_name);
2509                         bss->domain_name = domain_list;
2510                         bss->domain_name_len = domain_list_len;
2511                 } else if (os_strcmp(buf, "gas_frag_limit") == 0) {
2512                         bss->gas_frag_limit = atoi(pos);
2513                 } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
2514                         bss->gas_comeback_delay = atoi(pos);
2515 #endif /* CONFIG_INTERWORKING */
2516 #ifdef CONFIG_RADIUS_TEST
2517                 } else if (os_strcmp(buf, "dump_msk_file") == 0) {
2518                         os_free(bss->dump_msk_file);
2519                         bss->dump_msk_file = os_strdup(pos);
2520 #endif /* CONFIG_RADIUS_TEST */
2521 #ifdef CONFIG_HS20
2522                 } else if (os_strcmp(buf, "hs20") == 0) {
2523                         bss->hs20 = atoi(pos);
2524                 } else if (os_strcmp(buf, "disable_dgaf") == 0) {
2525                         bss->disable_dgaf = atoi(pos);
2526 #endif /* CONFIG_HS20 */
2527                 } else {
2528                         wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
2529                                    "item '%s'", line, buf);
2530                         errors++;
2531                 }
2532         }
2533
2534         return errors;
2535 }
2536
2537
2538 static void hostapd_set_security_params(struct hostapd_bss_config *bss)
2539 {
2540         int pairwise;
2541
2542         if (bss->individual_wep_key_len == 0) {
2543                 /* individual keys are not use; can use key idx0 for
2544                  * broadcast keys */
2545                 bss->broadcast_key_idx_min = 0;
2546         }
2547
2548         /* Select group cipher based on the enabled pairwise cipher
2549          * suites */
2550         pairwise = 0;
2551         if (bss->wpa & 1)
2552                 pairwise |= bss->wpa_pairwise;
2553         if (bss->wpa & 2) {
2554                 if (bss->rsn_pairwise == 0)
2555                         bss->rsn_pairwise = bss->wpa_pairwise;
2556                 pairwise |= bss->rsn_pairwise;
2557         }
2558         if (pairwise & WPA_CIPHER_TKIP)
2559                 bss->wpa_group = WPA_CIPHER_TKIP;
2560         else
2561                 bss->wpa_group = WPA_CIPHER_CCMP;
2562
2563         bss->radius->auth_server = bss->radius->auth_servers;
2564         bss->radius->acct_server = bss->radius->acct_servers;
2565
2566         if (bss->wpa && bss->ieee802_1x) {
2567                 bss->ssid.security_policy = SECURITY_WPA;
2568         } else if (bss->wpa) {
2569                 bss->ssid.security_policy = SECURITY_WPA_PSK;
2570         } else if (bss->ieee802_1x) {
2571                 int cipher = WPA_CIPHER_NONE;
2572                 bss->ssid.security_policy = SECURITY_IEEE_802_1X;
2573                 bss->ssid.wep.default_len = bss->default_wep_key_len;
2574                 if (bss->default_wep_key_len)
2575                         cipher = bss->default_wep_key_len >= 13 ?
2576                                 WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
2577                 bss->wpa_group = cipher;
2578                 bss->wpa_pairwise = cipher;
2579                 bss->rsn_pairwise = cipher;
2580         } else if (bss->ssid.wep.keys_set) {
2581                 int cipher = WPA_CIPHER_WEP40;
2582                 if (bss->ssid.wep.len[0] >= 13)
2583                         cipher = WPA_CIPHER_WEP104;
2584                 bss->ssid.security_policy = SECURITY_STATIC_WEP;
2585                 bss->wpa_group = cipher;
2586                 bss->wpa_pairwise = cipher;
2587                 bss->rsn_pairwise = cipher;
2588         } else {
2589                 bss->ssid.security_policy = SECURITY_PLAINTEXT;
2590                 bss->wpa_group = WPA_CIPHER_NONE;
2591                 bss->wpa_pairwise = WPA_CIPHER_NONE;
2592                 bss->rsn_pairwise = WPA_CIPHER_NONE;
2593         }
2594 }
2595
2596
2597 /**
2598  * hostapd_config_read - Read and parse a configuration file
2599  * @fname: Configuration file name (including path, if needed)
2600  * Returns: Allocated configuration data structure
2601  */
2602 struct hostapd_config * hostapd_config_read(const char *fname)
2603 {
2604         struct hostapd_config *conf;
2605         struct hostapd_bss_config *bss;
2606         FILE *f;
2607         char buf[512], *pos;
2608         int line = 0;
2609         int errors = 0;
2610         size_t i;
2611
2612         f = fopen(fname, "r");
2613         if (f == NULL) {
2614                 wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
2615                            "for reading.", fname);
2616                 return NULL;
2617         }
2618
2619         conf = hostapd_config_defaults();
2620         if (conf == NULL) {
2621                 fclose(f);
2622                 return NULL;
2623         }
2624
2625         /* set default driver based on configuration */
2626         conf->driver = wpa_drivers[0];
2627         if (conf->driver == NULL) {
2628                 wpa_printf(MSG_ERROR, "No driver wrappers registered!");
2629                 hostapd_config_free(conf);
2630                 fclose(f);
2631                 return NULL;
2632         }
2633
2634         bss = conf->last_bss = conf->bss;
2635
2636         while (fgets(buf, sizeof(buf), f)) {
2637                 bss = conf->last_bss;
2638                 line++;
2639
2640                 if (buf[0] == '#')
2641                         continue;
2642                 pos = buf;
2643                 while (*pos != '\0') {
2644                         if (*pos == '\n') {
2645                                 *pos = '\0';
2646                                 break;
2647                         }
2648                         pos++;
2649                 }
2650                 if (buf[0] == '\0')
2651                         continue;
2652
2653                 pos = os_strchr(buf, '=');
2654                 if (pos == NULL) {
2655                         wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
2656                                    line, buf);
2657                         errors++;
2658                         continue;
2659                 }
2660                 *pos = '\0';
2661                 pos++;
2662                 errors += hostapd_config_fill(conf, bss, buf, pos, line);
2663         }
2664
2665         fclose(f);
2666
2667         for (i = 0; i < conf->num_bss; i++)
2668                 hostapd_set_security_params(&conf->bss[i]);
2669
2670         if (hostapd_config_check(conf))
2671                 errors++;
2672
2673 #ifndef WPA_IGNORE_CONFIG_ERRORS
2674         if (errors) {
2675                 wpa_printf(MSG_ERROR, "%d errors found in configuration file "
2676                            "'%s'", errors, fname);
2677                 hostapd_config_free(conf);
2678                 conf = NULL;
2679         }
2680 #endif /* WPA_IGNORE_CONFIG_ERRORS */
2681
2682         return conf;
2683 }
2684
2685
2686 int hostapd_set_iface(struct hostapd_config *conf,
2687                       struct hostapd_bss_config *bss, char *field, char *value)
2688 {
2689         int errors;
2690         size_t i;
2691
2692         errors = hostapd_config_fill(conf, bss, field, value, 0);
2693         if (errors) {
2694                 wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
2695                            "to value '%s'", field, value);
2696                 return -1;
2697         }
2698
2699         for (i = 0; i < conf->num_bss; i++)
2700                 hostapd_set_security_params(&conf->bss[i]);
2701
2702         if (hostapd_config_check(conf)) {
2703                 wpa_printf(MSG_ERROR, "Configuration check failed");
2704                 return -1;
2705         }
2706
2707         return 0;
2708 }