Added support for setting VLAN ID for STAs based on local MAC ACL
[mech_eap.git] / hostapd / config.c
1 /*
2  * hostapd / Configuration file
3  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2007-2008, Intel Corporation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Alternatively, this software may be distributed under the terms of BSD
11  * license.
12  *
13  * See README and COPYING for more details.
14  */
15
16 #include "includes.h"
17 #ifndef CONFIG_NATIVE_WINDOWS
18 #include <grp.h>
19 #endif /* CONFIG_NATIVE_WINDOWS */
20
21 #include "hostapd.h"
22 #include "driver.h"
23 #include "sha1.h"
24 #include "eap_server/eap.h"
25 #include "radius/radius_client.h"
26 #include "wpa_common.h"
27 #include "wpa.h"
28 #include "uuid.h"
29
30
31 #define MAX_STA_COUNT 2007
32
33 extern struct wpa_driver_ops *hostapd_drivers[];
34
35
36 static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
37                                          const char *fname)
38 {
39         FILE *f;
40         char buf[128], *pos, *pos2;
41         int line = 0, vlan_id;
42         struct hostapd_vlan *vlan;
43
44         f = fopen(fname, "r");
45         if (!f) {
46                 printf("VLAN file '%s' not readable.\n", fname);
47                 return -1;
48         }
49
50         while (fgets(buf, sizeof(buf), f)) {
51                 line++;
52
53                 if (buf[0] == '#')
54                         continue;
55                 pos = buf;
56                 while (*pos != '\0') {
57                         if (*pos == '\n') {
58                                 *pos = '\0';
59                                 break;
60                         }
61                         pos++;
62                 }
63                 if (buf[0] == '\0')
64                         continue;
65
66                 if (buf[0] == '*') {
67                         vlan_id = VLAN_ID_WILDCARD;
68                         pos = buf + 1;
69                 } else {
70                         vlan_id = strtol(buf, &pos, 10);
71                         if (buf == pos || vlan_id < 1 ||
72                             vlan_id > MAX_VLAN_ID) {
73                                 printf("Invalid VLAN ID at line %d in '%s'\n",
74                                        line, fname);
75                                 fclose(f);
76                                 return -1;
77                         }
78                 }
79
80                 while (*pos == ' ' || *pos == '\t')
81                         pos++;
82                 pos2 = pos;
83                 while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
84                         pos2++;
85                 *pos2 = '\0';
86                 if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
87                         printf("Invalid VLAN ifname at line %d in '%s'\n",
88                                line, fname);
89                         fclose(f);
90                         return -1;
91                 }
92
93                 vlan = os_malloc(sizeof(*vlan));
94                 if (vlan == NULL) {
95                         printf("Out of memory while reading VLAN interfaces "
96                                "from '%s'\n", fname);
97                         fclose(f);
98                         return -1;
99                 }
100
101                 os_memset(vlan, 0, sizeof(*vlan));
102                 vlan->vlan_id = vlan_id;
103                 os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
104                 if (bss->vlan_tail)
105                         bss->vlan_tail->next = vlan;
106                 else
107                         bss->vlan = vlan;
108                 bss->vlan_tail = vlan;
109         }
110
111         fclose(f);
112
113         return 0;
114 }
115
116
117 static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
118 {
119         struct hostapd_vlan *vlan, *prev;
120
121         vlan = bss->vlan;
122         prev = NULL;
123         while (vlan) {
124                 prev = vlan;
125                 vlan = vlan->next;
126                 os_free(prev);
127         }
128
129         bss->vlan = NULL;
130 }
131
132
133 /* convert floats with one decimal place to value*10 int, i.e.,
134  * "1.5" will return 15 */
135 static int hostapd_config_read_int10(const char *value)
136 {
137         int i, d;
138         char *pos;
139
140         i = atoi(value);
141         pos = os_strchr(value, '.');
142         d = 0;
143         if (pos) {
144                 pos++;
145                 if (*pos >= '0' && *pos <= '9')
146                         d = *pos - '0';
147         }
148
149         return i * 10 + d;
150 }
151
152
153 static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
154 {
155         bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
156         bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
157         bss->logger_syslog = (unsigned int) -1;
158         bss->logger_stdout = (unsigned int) -1;
159
160         bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
161
162         bss->wep_rekeying_period = 300;
163         /* use key0 in individual key and key1 in broadcast key */
164         bss->broadcast_key_idx_min = 1;
165         bss->broadcast_key_idx_max = 2;
166         bss->eap_reauth_period = 3600;
167
168         bss->wpa_group_rekey = 600;
169         bss->wpa_gmk_rekey = 86400;
170         bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
171         bss->wpa_pairwise = WPA_CIPHER_TKIP;
172         bss->wpa_group = WPA_CIPHER_TKIP;
173         bss->rsn_pairwise = 0;
174
175         bss->max_num_sta = MAX_STA_COUNT;
176
177         bss->dtim_period = 2;
178
179         bss->radius_server_auth_port = 1812;
180         bss->ap_max_inactivity = AP_MAX_INACTIVITY;
181         bss->eapol_version = EAPOL_VERSION;
182
183         bss->max_listen_interval = 65535;
184 }
185
186
187 static struct hostapd_config * hostapd_config_defaults(void)
188 {
189         struct hostapd_config *conf;
190         struct hostapd_bss_config *bss;
191         int i;
192         const int aCWmin = 15, aCWmax = 1024;
193         const struct hostapd_wme_ac_params ac_bk =
194                 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
195         const struct hostapd_wme_ac_params ac_be =
196                 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
197         const struct hostapd_wme_ac_params ac_vi = /* video traffic */
198                 { aCWmin >> 1, aCWmin, 2, 3000 / 32, 1 };
199         const struct hostapd_wme_ac_params ac_vo = /* voice traffic */
200                 { aCWmin >> 2, aCWmin >> 1, 2, 1500 / 32, 1 };
201
202         conf = os_zalloc(sizeof(*conf));
203         bss = os_zalloc(sizeof(*bss));
204         if (conf == NULL || bss == NULL) {
205                 printf("Failed to allocate memory for configuration data.\n");
206                 os_free(conf);
207                 os_free(bss);
208                 return NULL;
209         }
210
211         /* set default driver based on configuration */
212         conf->driver = hostapd_drivers[0];
213         if (conf->driver == NULL) {
214                 printf("No driver wrappers registered!\n");
215                 os_free(conf);
216                 os_free(bss);
217                 return NULL;
218         }
219
220         bss->radius = os_zalloc(sizeof(*bss->radius));
221         if (bss->radius == NULL) {
222                 os_free(conf);
223                 os_free(bss);
224                 return NULL;
225         }
226
227         hostapd_config_defaults_bss(bss);
228
229         conf->num_bss = 1;
230         conf->bss = bss;
231
232         conf->beacon_int = 100;
233         conf->rts_threshold = -1; /* use driver default: 2347 */
234         conf->fragm_threshold = -1; /* user driver default: 2346 */
235         conf->send_probe_response = 1;
236         conf->bridge_packets = INTERNAL_BRIDGE_DO_NOT_CONTROL;
237
238         os_memcpy(conf->country, "US ", 3);
239
240         for (i = 0; i < NUM_TX_QUEUES; i++)
241                 conf->tx_queue[i].aifs = -1; /* use hw default */
242
243         conf->wme_ac_params[0] = ac_be;
244         conf->wme_ac_params[1] = ac_bk;
245         conf->wme_ac_params[2] = ac_vi;
246         conf->wme_ac_params[3] = ac_vo;
247
248 #ifdef CONFIG_IEEE80211N
249         SET_2BIT_LE16(&conf->ht_capab,
250                       HT_CAP_INFO_MIMO_PWR_SAVE_OFFSET,
251                       MIMO_PWR_NO_LIMIT_ON_MIMO_SEQS);
252
253         conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
254 #endif /* CONFIG_IEEE80211N */
255
256         return conf;
257 }
258
259
260 int hostapd_mac_comp(const void *a, const void *b)
261 {
262         return os_memcmp(a, b, sizeof(macaddr));
263 }
264
265
266 int hostapd_mac_comp_empty(const void *a)
267 {
268         macaddr empty = { 0 };
269         return os_memcmp(a, empty, sizeof(macaddr));
270 }
271
272
273 static int hostapd_acl_comp(const void *a, const void *b)
274 {
275         const struct mac_acl_entry *aa = a;
276         const struct mac_acl_entry *bb = b;
277         return os_memcmp(aa->addr, bb->addr, sizeof(macaddr));
278 }
279
280
281 static int hostapd_config_read_maclist(const char *fname,
282                                        struct mac_acl_entry **acl, int *num)
283 {
284         FILE *f;
285         char buf[128], *pos;
286         int line = 0;
287         u8 addr[ETH_ALEN];
288         struct mac_acl_entry *newacl;
289         int vlan_id;
290
291         if (!fname)
292                 return 0;
293
294         f = fopen(fname, "r");
295         if (!f) {
296                 printf("MAC list file '%s' not found.\n", fname);
297                 return -1;
298         }
299
300         while (fgets(buf, sizeof(buf), f)) {
301                 line++;
302
303                 if (buf[0] == '#')
304                         continue;
305                 pos = buf;
306                 while (*pos != '\0') {
307                         if (*pos == '\n') {
308                                 *pos = '\0';
309                                 break;
310                         }
311                         pos++;
312                 }
313                 if (buf[0] == '\0')
314                         continue;
315
316                 if (hwaddr_aton(buf, addr)) {
317                         printf("Invalid MAC address '%s' at line %d in '%s'\n",
318                                buf, line, fname);
319                         fclose(f);
320                         return -1;
321                 }
322
323                 vlan_id = 0;
324                 pos = buf;
325                 while (*pos != '\0' && *pos != ' ' && *pos != '\t')
326                         pos++;
327                 while (*pos == ' ' || *pos == '\t')
328                         pos++;
329                 if (*pos != '\0')
330                         vlan_id = atoi(pos);
331
332                 newacl = os_realloc(*acl, (*num + 1) * sizeof(**acl));
333                 if (newacl == NULL) {
334                         printf("MAC list reallocation failed\n");
335                         fclose(f);
336                         return -1;
337                 }
338
339                 *acl = newacl;
340                 os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
341                 (*acl)[*num].vlan_id = vlan_id;
342                 (*num)++;
343         }
344
345         fclose(f);
346
347         qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
348
349         return 0;
350 }
351
352
353 static int hostapd_config_read_wpa_psk(const char *fname,
354                                        struct hostapd_ssid *ssid)
355 {
356         FILE *f;
357         char buf[128], *pos;
358         int line = 0, ret = 0, len, ok;
359         u8 addr[ETH_ALEN];
360         struct hostapd_wpa_psk *psk;
361
362         if (!fname)
363                 return 0;
364
365         f = fopen(fname, "r");
366         if (!f) {
367                 printf("WPA PSK file '%s' not found.\n", fname);
368                 return -1;
369         }
370
371         while (fgets(buf, sizeof(buf), f)) {
372                 line++;
373
374                 if (buf[0] == '#')
375                         continue;
376                 pos = buf;
377                 while (*pos != '\0') {
378                         if (*pos == '\n') {
379                                 *pos = '\0';
380                                 break;
381                         }
382                         pos++;
383                 }
384                 if (buf[0] == '\0')
385                         continue;
386
387                 if (hwaddr_aton(buf, addr)) {
388                         printf("Invalid MAC address '%s' on line %d in '%s'\n",
389                                buf, line, fname);
390                         ret = -1;
391                         break;
392                 }
393
394                 psk = os_zalloc(sizeof(*psk));
395                 if (psk == NULL) {
396                         printf("WPA PSK allocation failed\n");
397                         ret = -1;
398                         break;
399                 }
400                 if (is_zero_ether_addr(addr))
401                         psk->group = 1;
402                 else
403                         os_memcpy(psk->addr, addr, ETH_ALEN);
404
405                 pos = buf + 17;
406                 if (pos == '\0') {
407                         printf("No PSK on line %d in '%s'\n", line, fname);
408                         os_free(psk);
409                         ret = -1;
410                         break;
411                 }
412                 pos++;
413
414                 ok = 0;
415                 len = os_strlen(pos);
416                 if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
417                         ok = 1;
418                 else if (len >= 8 && len < 64) {
419                         pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
420                                     4096, psk->psk, PMK_LEN);
421                         ok = 1;
422                 }
423                 if (!ok) {
424                         printf("Invalid PSK '%s' on line %d in '%s'\n",
425                                pos, line, fname);
426                         os_free(psk);
427                         ret = -1;
428                         break;
429                 }
430
431                 psk->next = ssid->wpa_psk;
432                 ssid->wpa_psk = psk;
433         }
434
435         fclose(f);
436
437         return ret;
438 }
439
440
441 int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
442 {
443         struct hostapd_ssid *ssid = &conf->ssid;
444
445         if (ssid->wpa_passphrase != NULL) {
446                 if (ssid->wpa_psk != NULL) {
447                         printf("Warning: both WPA PSK and passphrase set. "
448                                "Using passphrase.\n");
449                         os_free(ssid->wpa_psk);
450                 }
451                 ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
452                 if (ssid->wpa_psk == NULL) {
453                         printf("Unable to alloc space for PSK\n");
454                         return -1;
455                 }
456                 wpa_hexdump_ascii(MSG_DEBUG, "SSID",
457                                   (u8 *) ssid->ssid, ssid->ssid_len);
458                 wpa_hexdump_ascii(MSG_DEBUG, "PSK (ASCII passphrase)",
459                                   (u8 *) ssid->wpa_passphrase,
460                                   os_strlen(ssid->wpa_passphrase));
461                 pbkdf2_sha1(ssid->wpa_passphrase,
462                             ssid->ssid, ssid->ssid_len,
463                             4096, ssid->wpa_psk->psk, PMK_LEN);
464                 wpa_hexdump(MSG_DEBUG, "PSK (from passphrase)",
465                             ssid->wpa_psk->psk, PMK_LEN);
466                 ssid->wpa_psk->group = 1;
467
468                 os_memset(ssid->wpa_passphrase, 0,
469                           os_strlen(ssid->wpa_passphrase));
470                 os_free(ssid->wpa_passphrase);
471                 ssid->wpa_passphrase = NULL;
472         }
473
474         if (ssid->wpa_psk_file) {
475                 if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
476                                                 &conf->ssid))
477                         return -1;
478         }
479
480         return 0;
481 }
482
483
484 #ifdef EAP_SERVER
485 static int hostapd_config_read_eap_user(const char *fname,
486                                         struct hostapd_bss_config *conf)
487 {
488         FILE *f;
489         char buf[512], *pos, *start, *pos2;
490         int line = 0, ret = 0, num_methods;
491         struct hostapd_eap_user *user, *tail = NULL;
492
493         if (!fname)
494                 return 0;
495
496         f = fopen(fname, "r");
497         if (!f) {
498                 printf("EAP user file '%s' not found.\n", fname);
499                 return -1;
500         }
501
502         /* Lines: "user" METHOD,METHOD2 "password" (password optional) */
503         while (fgets(buf, sizeof(buf), f)) {
504                 line++;
505
506                 if (buf[0] == '#')
507                         continue;
508                 pos = buf;
509                 while (*pos != '\0') {
510                         if (*pos == '\n') {
511                                 *pos = '\0';
512                                 break;
513                         }
514                         pos++;
515                 }
516                 if (buf[0] == '\0')
517                         continue;
518
519                 user = NULL;
520
521                 if (buf[0] != '"' && buf[0] != '*') {
522                         printf("Invalid EAP identity (no \" in start) on "
523                                "line %d in '%s'\n", line, fname);
524                         goto failed;
525                 }
526
527                 user = os_zalloc(sizeof(*user));
528                 if (user == NULL) {
529                         printf("EAP user allocation failed\n");
530                         goto failed;
531                 }
532                 user->force_version = -1;
533
534                 if (buf[0] == '*') {
535                         pos = buf;
536                 } else {
537                         pos = buf + 1;
538                         start = pos;
539                         while (*pos != '"' && *pos != '\0')
540                                 pos++;
541                         if (*pos == '\0') {
542                                 printf("Invalid EAP identity (no \" in end) on"
543                                        " line %d in '%s'\n", line, fname);
544                                 goto failed;
545                         }
546
547                         user->identity = os_malloc(pos - start);
548                         if (user->identity == NULL) {
549                                 printf("Failed to allocate memory for EAP "
550                                        "identity\n");
551                                 goto failed;
552                         }
553                         os_memcpy(user->identity, start, pos - start);
554                         user->identity_len = pos - start;
555
556                         if (pos[0] == '"' && pos[1] == '*') {
557                                 user->wildcard_prefix = 1;
558                                 pos++;
559                         }
560                 }
561                 pos++;
562                 while (*pos == ' ' || *pos == '\t')
563                         pos++;
564
565                 if (*pos == '\0') {
566                         printf("No EAP method on line %d in '%s'\n",
567                                line, fname);
568                         goto failed;
569                 }
570
571                 start = pos;
572                 while (*pos != ' ' && *pos != '\t' && *pos != '\0')
573                         pos++;
574                 if (*pos == '\0') {
575                         pos = NULL;
576                 } else {
577                         *pos = '\0';
578                         pos++;
579                 }
580                 num_methods = 0;
581                 while (*start) {
582                         char *pos3 = os_strchr(start, ',');
583                         if (pos3) {
584                                 *pos3++ = '\0';
585                         }
586                         user->methods[num_methods].method =
587                                 eap_server_get_type(
588                                         start,
589                                         &user->methods[num_methods].vendor);
590                         if (user->methods[num_methods].vendor ==
591                             EAP_VENDOR_IETF &&
592                             user->methods[num_methods].method == EAP_TYPE_NONE)
593                         {
594                                 if (os_strcmp(start, "TTLS-PAP") == 0) {
595                                         user->ttls_auth |= EAP_TTLS_AUTH_PAP;
596                                         goto skip_eap;
597                                 }
598                                 if (os_strcmp(start, "TTLS-CHAP") == 0) {
599                                         user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
600                                         goto skip_eap;
601                                 }
602                                 if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
603                                         user->ttls_auth |=
604                                                 EAP_TTLS_AUTH_MSCHAP;
605                                         goto skip_eap;
606                                 }
607                                 if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
608                                         user->ttls_auth |=
609                                                 EAP_TTLS_AUTH_MSCHAPV2;
610                                         goto skip_eap;
611                                 }
612                                 printf("Unsupported EAP type '%s' on line %d "
613                                        "in '%s'\n", start, line, fname);
614                                 goto failed;
615                         }
616
617                         num_methods++;
618                         if (num_methods >= EAP_USER_MAX_METHODS)
619                                 break;
620                 skip_eap:
621                         if (pos3 == NULL)
622                                 break;
623                         start = pos3;
624                 }
625                 if (num_methods == 0 && user->ttls_auth == 0) {
626                         printf("No EAP types configured on line %d in '%s'\n",
627                                line, fname);
628                         goto failed;
629                 }
630
631                 if (pos == NULL)
632                         goto done;
633
634                 while (*pos == ' ' || *pos == '\t')
635                         pos++;
636                 if (*pos == '\0')
637                         goto done;
638
639                 if (os_strncmp(pos, "[ver=0]", 7) == 0) {
640                         user->force_version = 0;
641                         goto done;
642                 }
643
644                 if (os_strncmp(pos, "[ver=1]", 7) == 0) {
645                         user->force_version = 1;
646                         goto done;
647                 }
648
649                 if (os_strncmp(pos, "[2]", 3) == 0) {
650                         user->phase2 = 1;
651                         goto done;
652                 }
653
654                 if (*pos == '"') {
655                         pos++;
656                         start = pos;
657                         while (*pos != '"' && *pos != '\0')
658                                 pos++;
659                         if (*pos == '\0') {
660                                 printf("Invalid EAP password (no \" in end) "
661                                        "on line %d in '%s'\n", line, fname);
662                                 goto failed;
663                         }
664
665                         user->password = os_malloc(pos - start);
666                         if (user->password == NULL) {
667                                 printf("Failed to allocate memory for EAP "
668                                        "password\n");
669                                 goto failed;
670                         }
671                         os_memcpy(user->password, start, pos - start);
672                         user->password_len = pos - start;
673
674                         pos++;
675                 } else if (os_strncmp(pos, "hash:", 5) == 0) {
676                         pos += 5;
677                         pos2 = pos;
678                         while (*pos2 != '\0' && *pos2 != ' ' &&
679                                *pos2 != '\t' && *pos2 != '#')
680                                 pos2++;
681                         if (pos2 - pos != 32) {
682                                 printf("Invalid password hash on line %d in "
683                                        "'%s'\n", line, fname);
684                                 goto failed;
685                         }
686                         user->password = os_malloc(16);
687                         if (user->password == NULL) {
688                                 printf("Failed to allocate memory for EAP "
689                                        "password hash\n");
690                                 goto failed;
691                         }
692                         if (hexstr2bin(pos, user->password, 16) < 0) {
693                                 printf("Invalid hash password on line %d in "
694                                        "'%s'\n", line, fname);
695                                 goto failed;
696                         }
697                         user->password_len = 16;
698                         user->password_hash = 1;
699                         pos = pos2;
700                 } else {
701                         pos2 = pos;
702                         while (*pos2 != '\0' && *pos2 != ' ' &&
703                                *pos2 != '\t' && *pos2 != '#')
704                                 pos2++;
705                         if ((pos2 - pos) & 1) {
706                                 printf("Invalid hex password on line %d in "
707                                        "'%s'\n", line, fname);
708                                 goto failed;
709                         }
710                         user->password = os_malloc((pos2 - pos) / 2);
711                         if (user->password == NULL) {
712                                 printf("Failed to allocate memory for EAP "
713                                        "password\n");
714                                 goto failed;
715                         }
716                         if (hexstr2bin(pos, user->password,
717                                        (pos2 - pos) / 2) < 0) {
718                                 printf("Invalid hex password on line %d in "
719                                        "'%s'\n", line, fname);
720                                 goto failed;
721                         }
722                         user->password_len = (pos2 - pos) / 2;
723                         pos = pos2;
724                 }
725
726                 while (*pos == ' ' || *pos == '\t')
727                         pos++;
728                 if (os_strncmp(pos, "[2]", 3) == 0) {
729                         user->phase2 = 1;
730                 }
731
732         done:
733                 if (tail == NULL) {
734                         tail = conf->eap_user = user;
735                 } else {
736                         tail->next = user;
737                         tail = user;
738                 }
739                 continue;
740
741         failed:
742                 if (user) {
743                         os_free(user->password);
744                         os_free(user->identity);
745                         os_free(user);
746                 }
747                 ret = -1;
748                 break;
749         }
750
751         fclose(f);
752
753         return ret;
754 }
755 #endif /* EAP_SERVER */
756
757
758 static int
759 hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
760                                 int *num_server, const char *val, int def_port,
761                                 struct hostapd_radius_server **curr_serv)
762 {
763         struct hostapd_radius_server *nserv;
764         int ret;
765         static int server_index = 1;
766
767         nserv = os_realloc(*server, (*num_server + 1) * sizeof(*nserv));
768         if (nserv == NULL)
769                 return -1;
770
771         *server = nserv;
772         nserv = &nserv[*num_server];
773         (*num_server)++;
774         (*curr_serv) = nserv;
775
776         os_memset(nserv, 0, sizeof(*nserv));
777         nserv->port = def_port;
778         ret = hostapd_parse_ip_addr(val, &nserv->addr);
779         nserv->index = server_index++;
780
781         return ret;
782 }
783
784
785 static int hostapd_config_parse_key_mgmt(int line, const char *value)
786 {
787         int val = 0, last;
788         char *start, *end, *buf;
789
790         buf = os_strdup(value);
791         if (buf == NULL)
792                 return -1;
793         start = buf;
794
795         while (start != '\0') {
796                 while (*start == ' ' || *start == '\t')
797                         start++;
798                 if (*start == '\0')
799                         break;
800                 end = start;
801                 while (*end != ' ' && *end != '\t' && *end != '\0')
802                         end++;
803                 last = *end == '\0';
804                 *end = '\0';
805                 if (os_strcmp(start, "WPA-PSK") == 0)
806                         val |= WPA_KEY_MGMT_PSK;
807                 else if (os_strcmp(start, "WPA-EAP") == 0)
808                         val |= WPA_KEY_MGMT_IEEE8021X;
809 #ifdef CONFIG_IEEE80211R
810                 else if (os_strcmp(start, "FT-PSK") == 0)
811                         val |= WPA_KEY_MGMT_FT_PSK;
812                 else if (os_strcmp(start, "FT-EAP") == 0)
813                         val |= WPA_KEY_MGMT_FT_IEEE8021X;
814 #endif /* CONFIG_IEEE80211R */
815                 else {
816                         printf("Line %d: invalid key_mgmt '%s'\n",
817                                line, start);
818                         os_free(buf);
819                         return -1;
820                 }
821
822                 if (last)
823                         break;
824                 start = end + 1;
825         }
826
827         os_free(buf);
828         if (val == 0) {
829                 printf("Line %d: no key_mgmt values configured.\n", line);
830                 return -1;
831         }
832
833         return val;
834 }
835
836
837 static int hostapd_config_parse_cipher(int line, const char *value)
838 {
839         int val = 0, last;
840         char *start, *end, *buf;
841
842         buf = os_strdup(value);
843         if (buf == NULL)
844                 return -1;
845         start = buf;
846
847         while (start != '\0') {
848                 while (*start == ' ' || *start == '\t')
849                         start++;
850                 if (*start == '\0')
851                         break;
852                 end = start;
853                 while (*end != ' ' && *end != '\t' && *end != '\0')
854                         end++;
855                 last = *end == '\0';
856                 *end = '\0';
857                 if (os_strcmp(start, "CCMP") == 0)
858                         val |= WPA_CIPHER_CCMP;
859                 else if (os_strcmp(start, "TKIP") == 0)
860                         val |= WPA_CIPHER_TKIP;
861                 else if (os_strcmp(start, "WEP104") == 0)
862                         val |= WPA_CIPHER_WEP104;
863                 else if (os_strcmp(start, "WEP40") == 0)
864                         val |= WPA_CIPHER_WEP40;
865                 else if (os_strcmp(start, "NONE") == 0)
866                         val |= WPA_CIPHER_NONE;
867                 else {
868                         printf("Line %d: invalid cipher '%s'.", line, start);
869                         os_free(buf);
870                         return -1;
871                 }
872
873                 if (last)
874                         break;
875                 start = end + 1;
876         }
877         os_free(buf);
878
879         if (val == 0) {
880                 printf("Line %d: no cipher values configured.", line);
881                 return -1;
882         }
883         return val;
884 }
885
886
887 static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
888                                     struct hostapd_config *conf)
889 {
890         if (bss->ieee802_1x && !bss->eap_server &&
891             !bss->radius->auth_servers) {
892                 printf("Invalid IEEE 802.1X configuration (no EAP "
893                        "authenticator configured).\n");
894                 return -1;
895         }
896
897         if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
898             bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
899             bss->ssid.wpa_psk_file == NULL) {
900                 printf("WPA-PSK enabled, but PSK or passphrase is not "
901                        "configured.\n");
902                 return -1;
903         }
904
905         if (hostapd_mac_comp_empty(bss->bssid) != 0) {
906                 size_t i;
907
908                 for (i = 0; i < conf->num_bss; i++) {
909                         if ((&conf->bss[i] != bss) &&
910                             (hostapd_mac_comp(conf->bss[i].bssid,
911                                               bss->bssid) == 0)) {
912                                 printf("Duplicate BSSID " MACSTR
913                                        " on interface '%s' and '%s'.\n",
914                                        MAC2STR(bss->bssid),
915                                        conf->bss[i].iface, bss->iface);
916                                 return -1;
917                         }
918                 }
919         }
920
921 #ifdef CONFIG_IEEE80211R
922         if ((bss->wpa_key_mgmt &
923              (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) &&
924             (bss->nas_identifier == NULL ||
925              os_strlen(bss->nas_identifier) < 1 ||
926              os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
927                 printf("FT (IEEE 802.11r) requires nas_identifier to be "
928                        "configured as a 1..48 octet string\n");
929                 return -1;
930         }
931 #endif /* CONFIG_IEEE80211R */
932
933         return 0;
934 }
935
936
937 static int hostapd_config_check(struct hostapd_config *conf)
938 {
939         size_t i;
940
941         for (i = 0; i < conf->num_bss; i++) {
942                 if (hostapd_config_check_bss(&conf->bss[i], conf))
943                         return -1;
944         }
945
946         return 0;
947 }
948
949
950 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
951                                    char *val)
952 {
953         size_t len = os_strlen(val);
954
955         if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL)
956                 return -1;
957
958         if (val[0] == '"') {
959                 if (len < 2 || val[len - 1] != '"')
960                         return -1;
961                 len -= 2;
962                 wep->key[keyidx] = os_malloc(len);
963                 if (wep->key[keyidx] == NULL)
964                         return -1;
965                 os_memcpy(wep->key[keyidx], val + 1, len);
966                 wep->len[keyidx] = len;
967         } else {
968                 if (len & 1)
969                         return -1;
970                 len /= 2;
971                 wep->key[keyidx] = os_malloc(len);
972                 if (wep->key[keyidx] == NULL)
973                         return -1;
974                 wep->len[keyidx] = len;
975                 if (hexstr2bin(val, wep->key[keyidx], len) < 0)
976                         return -1;
977         }
978
979         wep->keys_set++;
980
981         return 0;
982 }
983
984
985 static int hostapd_parse_rates(int **rate_list, char *val)
986 {
987         int *list;
988         int count;
989         char *pos, *end;
990
991         os_free(*rate_list);
992         *rate_list = NULL;
993
994         pos = val;
995         count = 0;
996         while (*pos != '\0') {
997                 if (*pos == ' ')
998                         count++;
999                 pos++;
1000         }
1001
1002         list = os_malloc(sizeof(int) * (count + 2));
1003         if (list == NULL)
1004                 return -1;
1005         pos = val;
1006         count = 0;
1007         while (*pos != '\0') {
1008                 end = os_strchr(pos, ' ');
1009                 if (end)
1010                         *end = '\0';
1011
1012                 list[count++] = atoi(pos);
1013                 if (!end)
1014                         break;
1015                 pos = end + 1;
1016         }
1017         list[count] = -1;
1018
1019         *rate_list = list;
1020         return 0;
1021 }
1022
1023
1024 static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
1025 {
1026         struct hostapd_bss_config *bss;
1027
1028         if (*ifname == '\0')
1029                 return -1;
1030
1031         bss = os_realloc(conf->bss, (conf->num_bss + 1) *
1032                          sizeof(struct hostapd_bss_config));
1033         if (bss == NULL) {
1034                 printf("Failed to allocate memory for multi-BSS entry\n");
1035                 return -1;
1036         }
1037         conf->bss = bss;
1038
1039         bss = &(conf->bss[conf->num_bss]);
1040         os_memset(bss, 0, sizeof(*bss));
1041         bss->radius = os_zalloc(sizeof(*bss->radius));
1042         if (bss->radius == NULL) {
1043                 printf("Failed to allocate memory for multi-BSS RADIUS "
1044                        "data\n");
1045                 return -1;
1046         }
1047
1048         conf->num_bss++;
1049         conf->last_bss = bss;
1050
1051         hostapd_config_defaults_bss(bss);
1052         os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
1053         os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
1054
1055         return 0;
1056 }
1057
1058
1059 static int valid_cw(int cw)
1060 {
1061         return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
1062                 cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023);
1063 }
1064
1065
1066 enum {
1067         IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
1068         IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
1069         IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
1070         IEEE80211_TX_QUEUE_DATA3 = 3, /* used for EDCA AC_BK data */
1071         IEEE80211_TX_QUEUE_DATA4 = 4,
1072         IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
1073         IEEE80211_TX_QUEUE_BEACON = 7
1074 };
1075
1076 static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
1077                                    char *val)
1078 {
1079         int num;
1080         char *pos;
1081         struct hostapd_tx_queue_params *queue;
1082
1083         /* skip 'tx_queue_' prefix */
1084         pos = name + 9;
1085         if (os_strncmp(pos, "data", 4) == 0 &&
1086             pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
1087                 num = pos[4] - '0';
1088                 pos += 6;
1089         } else if (os_strncmp(pos, "after_beacon_", 13) == 0) {
1090                 num = IEEE80211_TX_QUEUE_AFTER_BEACON;
1091                 pos += 13;
1092         } else if (os_strncmp(pos, "beacon_", 7) == 0) {
1093                 num = IEEE80211_TX_QUEUE_BEACON;
1094                 pos += 7;
1095         } else {
1096                 printf("Unknown tx_queue name '%s'\n", pos);
1097                 return -1;
1098         }
1099
1100         queue = &conf->tx_queue[num];
1101
1102         if (os_strcmp(pos, "aifs") == 0) {
1103                 queue->aifs = atoi(val);
1104                 if (queue->aifs < 0 || queue->aifs > 255) {
1105                         printf("Invalid AIFS value %d\n", queue->aifs);
1106                         return -1;
1107                 }
1108         } else if (os_strcmp(pos, "cwmin") == 0) {
1109                 queue->cwmin = atoi(val);
1110                 if (!valid_cw(queue->cwmin)) {
1111                         printf("Invalid cwMin value %d\n", queue->cwmin);
1112                         return -1;
1113                 }
1114         } else if (os_strcmp(pos, "cwmax") == 0) {
1115                 queue->cwmax = atoi(val);
1116                 if (!valid_cw(queue->cwmax)) {
1117                         printf("Invalid cwMax value %d\n", queue->cwmax);
1118                         return -1;
1119                 }
1120         } else if (os_strcmp(pos, "burst") == 0) {
1121                 queue->burst = hostapd_config_read_int10(val);
1122         } else {
1123                 printf("Unknown tx_queue field '%s'\n", pos);
1124                 return -1;
1125         }
1126
1127         queue->configured = 1;
1128
1129         return 0;
1130 }
1131
1132
1133 static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name,
1134                                    char *val)
1135 {
1136         int num, v;
1137         char *pos;
1138         struct hostapd_wme_ac_params *ac;
1139
1140         /* skip 'wme_ac_' prefix */
1141         pos = name + 7;
1142         if (os_strncmp(pos, "be_", 3) == 0) {
1143                 num = 0;
1144                 pos += 3;
1145         } else if (os_strncmp(pos, "bk_", 3) == 0) {
1146                 num = 1;
1147                 pos += 3;
1148         } else if (os_strncmp(pos, "vi_", 3) == 0) {
1149                 num = 2;
1150                 pos += 3;
1151         } else if (os_strncmp(pos, "vo_", 3) == 0) {
1152                 num = 3;
1153                 pos += 3;
1154         } else {
1155                 printf("Unknown wme name '%s'\n", pos);
1156                 return -1;
1157         }
1158
1159         ac = &conf->wme_ac_params[num];
1160
1161         if (os_strcmp(pos, "aifs") == 0) {
1162                 v = atoi(val);
1163                 if (v < 1 || v > 255) {
1164                         printf("Invalid AIFS value %d\n", v);
1165                         return -1;
1166                 }
1167                 ac->aifs = v;
1168         } else if (os_strcmp(pos, "cwmin") == 0) {
1169                 v = atoi(val);
1170                 if (v < 0 || v > 12) {
1171                         printf("Invalid cwMin value %d\n", v);
1172                         return -1;
1173                 }
1174                 ac->cwmin = v;
1175         } else if (os_strcmp(pos, "cwmax") == 0) {
1176                 v = atoi(val);
1177                 if (v < 0 || v > 12) {
1178                         printf("Invalid cwMax value %d\n", v);
1179                         return -1;
1180                 }
1181                 ac->cwmax = v;
1182         } else if (os_strcmp(pos, "txop_limit") == 0) {
1183                 v = atoi(val);
1184                 if (v < 0 || v > 0xffff) {
1185                         printf("Invalid txop value %d\n", v);
1186                         return -1;
1187                 }
1188                 ac->txopLimit = v;
1189         } else if (os_strcmp(pos, "acm") == 0) {
1190                 v = atoi(val);
1191                 if (v < 0 || v > 1) {
1192                         printf("Invalid acm value %d\n", v);
1193                         return -1;
1194                 }
1195                 ac->admission_control_mandatory = v;
1196         } else {
1197                 printf("Unknown wme_ac_ field '%s'\n", pos);
1198                 return -1;
1199         }
1200
1201         return 0;
1202 }
1203
1204
1205 #ifdef CONFIG_IEEE80211R
1206 static int add_r0kh(struct hostapd_bss_config *bss, char *value)
1207 {
1208         struct ft_remote_r0kh *r0kh;
1209         char *pos, *next;
1210
1211         r0kh = os_zalloc(sizeof(*r0kh));
1212         if (r0kh == NULL)
1213                 return -1;
1214
1215         /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
1216         pos = value;
1217         next = os_strchr(pos, ' ');
1218         if (next)
1219                 *next++ = '\0';
1220         if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
1221                 printf("Invalid R0KH MAC address: '%s'\n", pos);
1222                 os_free(r0kh);
1223                 return -1;
1224         }
1225
1226         pos = next;
1227         next = os_strchr(pos, ' ');
1228         if (next)
1229                 *next++ = '\0';
1230         if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
1231                 printf("Invalid R0KH-ID: '%s'\n", pos);
1232                 os_free(r0kh);
1233                 return -1;
1234         }
1235         r0kh->id_len = next - pos - 1;
1236         os_memcpy(r0kh->id, pos, r0kh->id_len);
1237
1238         pos = next;
1239         if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) {
1240                 printf("Invalid R0KH key: '%s'\n", pos);
1241                 os_free(r0kh);
1242                 return -1;
1243         }
1244
1245         r0kh->next = bss->r0kh_list;
1246         bss->r0kh_list = r0kh;
1247
1248         return 0;
1249 }
1250
1251
1252 static int add_r1kh(struct hostapd_bss_config *bss, char *value)
1253 {
1254         struct ft_remote_r1kh *r1kh;
1255         char *pos, *next;
1256
1257         r1kh = os_zalloc(sizeof(*r1kh));
1258         if (r1kh == NULL)
1259                 return -1;
1260
1261         /* 02:01:02:03:04:05 02:01:02:03:04:05
1262          * 000102030405060708090a0b0c0d0e0f */
1263         pos = value;
1264         next = os_strchr(pos, ' ');
1265         if (next)
1266                 *next++ = '\0';
1267         if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
1268                 printf("Invalid R1KH MAC address: '%s'\n", pos);
1269                 os_free(r1kh);
1270                 return -1;
1271         }
1272
1273         pos = next;
1274         next = os_strchr(pos, ' ');
1275         if (next)
1276                 *next++ = '\0';
1277         if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
1278                 printf("Invalid R1KH-ID: '%s'\n", pos);
1279                 os_free(r1kh);
1280                 return -1;
1281         }
1282
1283         pos = next;
1284         if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) {
1285                 printf("Invalid R1KH key: '%s'\n", pos);
1286                 os_free(r1kh);
1287                 return -1;
1288         }
1289
1290         r1kh->next = bss->r1kh_list;
1291         bss->r1kh_list = r1kh;
1292
1293         return 0;
1294 }
1295 #endif /* CONFIG_IEEE80211R */
1296
1297
1298 struct hostapd_config * hostapd_config_read(const char *fname)
1299 {
1300         struct hostapd_config *conf;
1301         struct hostapd_bss_config *bss;
1302         FILE *f;
1303         char buf[256], *pos;
1304         int line = 0;
1305         int errors = 0;
1306         int pairwise;
1307         size_t i;
1308
1309         f = fopen(fname, "r");
1310         if (f == NULL) {
1311                 printf("Could not open configuration file '%s' for reading.\n",
1312                        fname);
1313                 return NULL;
1314         }
1315
1316         conf = hostapd_config_defaults();
1317         if (conf == NULL) {
1318                 fclose(f);
1319                 return NULL;
1320         }
1321         bss = conf->last_bss = conf->bss;
1322
1323         while (fgets(buf, sizeof(buf), f)) {
1324                 bss = conf->last_bss;
1325                 line++;
1326
1327                 if (buf[0] == '#')
1328                         continue;
1329                 pos = buf;
1330                 while (*pos != '\0') {
1331                         if (*pos == '\n') {
1332                                 *pos = '\0';
1333                                 break;
1334                         }
1335                         pos++;
1336                 }
1337                 if (buf[0] == '\0')
1338                         continue;
1339
1340                 pos = os_strchr(buf, '=');
1341                 if (pos == NULL) {
1342                         printf("Line %d: invalid line '%s'\n", line, buf);
1343                         errors++;
1344                         continue;
1345                 }
1346                 *pos = '\0';
1347                 pos++;
1348
1349                 if (os_strcmp(buf, "interface") == 0) {
1350                         os_strlcpy(conf->bss[0].iface, pos,
1351                                    sizeof(conf->bss[0].iface));
1352                 } else if (os_strcmp(buf, "bridge") == 0) {
1353                         os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
1354                 } else if (os_strcmp(buf, "driver") == 0) {
1355                         int i;
1356                         /* clear to get error below if setting is invalid */
1357                         conf->driver = NULL;
1358                         for (i = 0; hostapd_drivers[i]; i++) {
1359                                 if (os_strcmp(pos, hostapd_drivers[i]->name) ==
1360                                     0) {
1361                                         conf->driver = hostapd_drivers[i];
1362                                         break;
1363                                 }
1364                         }
1365                         if (conf->driver == NULL) {
1366                                 printf("Line %d: invalid/unknown driver "
1367                                        "'%s'\n", line, pos);
1368                                 errors++;
1369                         }
1370                 } else if (os_strcmp(buf, "debug") == 0) {
1371                         wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' "
1372                                    "configuration variable is not used "
1373                                    "anymore", line);
1374                 } else if (os_strcmp(buf, "logger_syslog_level") == 0) {
1375                         bss->logger_syslog_level = atoi(pos);
1376                 } else if (os_strcmp(buf, "logger_stdout_level") == 0) {
1377                         bss->logger_stdout_level = atoi(pos);
1378                 } else if (os_strcmp(buf, "logger_syslog") == 0) {
1379                         bss->logger_syslog = atoi(pos);
1380                 } else if (os_strcmp(buf, "logger_stdout") == 0) {
1381                         bss->logger_stdout = atoi(pos);
1382                 } else if (os_strcmp(buf, "dump_file") == 0) {
1383                         bss->dump_log_name = os_strdup(pos);
1384                 } else if (os_strcmp(buf, "ssid") == 0) {
1385                         bss->ssid.ssid_len = os_strlen(pos);
1386                         if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
1387                             bss->ssid.ssid_len < 1) {
1388                                 printf("Line %d: invalid SSID '%s'\n", line,
1389                                        pos);
1390                                 errors++;
1391                         } else {
1392                                 os_memcpy(bss->ssid.ssid, pos,
1393                                           bss->ssid.ssid_len);
1394                                 bss->ssid.ssid[bss->ssid.ssid_len] = '\0';
1395                                 bss->ssid.ssid_set = 1;
1396                         }
1397                 } else if (os_strcmp(buf, "macaddr_acl") == 0) {
1398                         bss->macaddr_acl = atoi(pos);
1399                         if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
1400                             bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
1401                             bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1402                                 printf("Line %d: unknown macaddr_acl %d\n",
1403                                        line, bss->macaddr_acl);
1404                         }
1405                 } else if (os_strcmp(buf, "accept_mac_file") == 0) {
1406                         if (hostapd_config_read_maclist(pos, &bss->accept_mac,
1407                                                         &bss->num_accept_mac))
1408                         {
1409                                 printf("Line %d: Failed to read "
1410                                        "accept_mac_file '%s'\n",
1411                                        line, pos);
1412                                 errors++;
1413                         }
1414                 } else if (os_strcmp(buf, "deny_mac_file") == 0) {
1415                         if (hostapd_config_read_maclist(pos, &bss->deny_mac,
1416                                                         &bss->num_deny_mac))
1417                         {
1418                                 printf("Line %d: Failed to read "
1419                                        "deny_mac_file '%s'\n",
1420                                        line, pos);
1421                                 errors++;
1422                         }
1423                 } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
1424                         bss->ap_max_inactivity = atoi(pos);
1425                 } else if (os_strcmp(buf, "country_code") == 0) {
1426                         os_memcpy(conf->country, pos, 2);
1427                         /* FIX: make this configurable */
1428                         conf->country[2] = ' ';
1429                 } else if (os_strcmp(buf, "ieee80211d") == 0) {
1430                         conf->ieee80211d = atoi(pos);
1431                 } else if (os_strcmp(buf, "ieee80211h") == 0) {
1432                         conf->ieee80211h = atoi(pos);
1433                 } else if (os_strcmp(buf, "assoc_ap_addr") == 0) {
1434                         if (hwaddr_aton(pos, bss->assoc_ap_addr)) {
1435                                 printf("Line %d: invalid MAC address '%s'\n",
1436                                        line, pos);
1437                                 errors++;
1438                         }
1439                         bss->assoc_ap = 1;
1440                 } else if (os_strcmp(buf, "ieee8021x") == 0) {
1441                         bss->ieee802_1x = atoi(pos);
1442                 } else if (os_strcmp(buf, "eapol_version") == 0) {
1443                         bss->eapol_version = atoi(pos);
1444                         if (bss->eapol_version < 1 ||
1445                             bss->eapol_version > 2) {
1446                                 printf("Line %d: invalid EAPOL "
1447                                        "version (%d): '%s'.\n",
1448                                        line, bss->eapol_version, pos);
1449                                 errors++;
1450                         } else
1451                                 wpa_printf(MSG_DEBUG, "eapol_version=%d",
1452                                            bss->eapol_version);
1453 #ifdef EAP_SERVER
1454                 } else if (os_strcmp(buf, "eap_authenticator") == 0) {
1455                         bss->eap_server = atoi(pos);
1456                         printf("Line %d: obsolete eap_authenticator used; "
1457                                "this has been renamed to eap_server\n", line);
1458                 } else if (os_strcmp(buf, "eap_server") == 0) {
1459                         bss->eap_server = atoi(pos);
1460                 } else if (os_strcmp(buf, "eap_user_file") == 0) {
1461                         if (hostapd_config_read_eap_user(pos, bss))
1462                                 errors++;
1463                 } else if (os_strcmp(buf, "ca_cert") == 0) {
1464                         os_free(bss->ca_cert);
1465                         bss->ca_cert = os_strdup(pos);
1466                 } else if (os_strcmp(buf, "server_cert") == 0) {
1467                         os_free(bss->server_cert);
1468                         bss->server_cert = os_strdup(pos);
1469                 } else if (os_strcmp(buf, "private_key") == 0) {
1470                         os_free(bss->private_key);
1471                         bss->private_key = os_strdup(pos);
1472                 } else if (os_strcmp(buf, "private_key_passwd") == 0) {
1473                         os_free(bss->private_key_passwd);
1474                         bss->private_key_passwd = os_strdup(pos);
1475                 } else if (os_strcmp(buf, "check_crl") == 0) {
1476                         bss->check_crl = atoi(pos);
1477                 } else if (os_strcmp(buf, "dh_file") == 0) {
1478                         os_free(bss->dh_file);
1479                         bss->dh_file = os_strdup(pos);
1480 #ifdef EAP_FAST
1481                 } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
1482                         os_free(bss->pac_opaque_encr_key);
1483                         bss->pac_opaque_encr_key = os_malloc(16);
1484                         if (bss->pac_opaque_encr_key == NULL) {
1485                                 printf("Line %d: No memory for "
1486                                        "pac_opque_encr_key\n", line);
1487                                 errors++;
1488                         } else if (hexstr2bin(pos, bss->pac_opaque_encr_key,
1489                                               16)) {
1490                                 printf("Line %d: Invalid pac_opque_encr_key\n",
1491                                        line);
1492                                 errors++;
1493                         }
1494                 } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
1495                         os_free(bss->eap_fast_a_id);
1496                         bss->eap_fast_a_id = os_strdup(pos);
1497 #endif /* EAP_FAST */
1498 #ifdef EAP_SIM
1499                 } else if (os_strcmp(buf, "eap_sim_db") == 0) {
1500                         os_free(bss->eap_sim_db);
1501                         bss->eap_sim_db = os_strdup(pos);
1502                 } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
1503                         bss->eap_sim_aka_result_ind = atoi(pos);
1504 #endif /* EAP_SIM */
1505 #ifdef EAP_TNC
1506                 } else if (os_strcmp(buf, "tnc") == 0) {
1507                         bss->tnc = atoi(pos);
1508 #endif /* EAP_TNC */
1509 #endif /* EAP_SERVER */
1510                 } else if (os_strcmp(buf, "eap_message") == 0) {
1511                         char *term;
1512                         bss->eap_req_id_text = os_strdup(pos);
1513                         if (bss->eap_req_id_text == NULL) {
1514                                 printf("Line %d: Failed to allocate memory "
1515                                        "for eap_req_id_text\n", line);
1516                                 errors++;
1517                                 continue;
1518                         }
1519                         bss->eap_req_id_text_len =
1520                                 os_strlen(bss->eap_req_id_text);
1521                         term = os_strstr(bss->eap_req_id_text, "\\0");
1522                         if (term) {
1523                                 *term++ = '\0';
1524                                 os_memmove(term, term + 1,
1525                                            bss->eap_req_id_text_len -
1526                                            (term - bss->eap_req_id_text) - 1);
1527                                 bss->eap_req_id_text_len--;
1528                         }
1529                 } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
1530                         bss->default_wep_key_len = atoi(pos);
1531                         if (bss->default_wep_key_len > 13) {
1532                                 printf("Line %d: invalid WEP key len %lu "
1533                                        "(= %lu bits)\n", line,
1534                                        (unsigned long)
1535                                        bss->default_wep_key_len,
1536                                        (unsigned long)
1537                                        bss->default_wep_key_len * 8);
1538                                 errors++;
1539                         }
1540                 } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
1541                         bss->individual_wep_key_len = atoi(pos);
1542                         if (bss->individual_wep_key_len < 0 ||
1543                             bss->individual_wep_key_len > 13) {
1544                                 printf("Line %d: invalid WEP key len %d "
1545                                        "(= %d bits)\n", line,
1546                                        bss->individual_wep_key_len,
1547                                        bss->individual_wep_key_len * 8);
1548                                 errors++;
1549                         }
1550                 } else if (os_strcmp(buf, "wep_rekey_period") == 0) {
1551                         bss->wep_rekeying_period = atoi(pos);
1552                         if (bss->wep_rekeying_period < 0) {
1553                                 printf("Line %d: invalid period %d\n",
1554                                        line, bss->wep_rekeying_period);
1555                                 errors++;
1556                         }
1557                 } else if (os_strcmp(buf, "eap_reauth_period") == 0) {
1558                         bss->eap_reauth_period = atoi(pos);
1559                         if (bss->eap_reauth_period < 0) {
1560                                 printf("Line %d: invalid period %d\n",
1561                                        line, bss->eap_reauth_period);
1562                                 errors++;
1563                         }
1564                 } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
1565                         bss->eapol_key_index_workaround = atoi(pos);
1566 #ifdef CONFIG_IAPP
1567                 } else if (os_strcmp(buf, "iapp_interface") == 0) {
1568                         bss->ieee802_11f = 1;
1569                         os_strlcpy(bss->iapp_iface, pos,
1570                                    sizeof(bss->iapp_iface));
1571 #endif /* CONFIG_IAPP */
1572                 } else if (os_strcmp(buf, "own_ip_addr") == 0) {
1573                         if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
1574                                 printf("Line %d: invalid IP address '%s'\n",
1575                                        line, pos);
1576                                 errors++;
1577                         }
1578                 } else if (os_strcmp(buf, "nas_identifier") == 0) {
1579                         bss->nas_identifier = os_strdup(pos);
1580                 } else if (os_strcmp(buf, "auth_server_addr") == 0) {
1581                         if (hostapd_config_read_radius_addr(
1582                                     &bss->radius->auth_servers,
1583                                     &bss->radius->num_auth_servers, pos, 1812,
1584                                     &bss->radius->auth_server)) {
1585                                 printf("Line %d: invalid IP address '%s'\n",
1586                                        line, pos);
1587                                 errors++;
1588                         }
1589                 } else if (bss->radius->auth_server &&
1590                            os_strcmp(buf, "auth_server_port") == 0) {
1591                         bss->radius->auth_server->port = atoi(pos);
1592                 } else if (bss->radius->auth_server &&
1593                            os_strcmp(buf, "auth_server_shared_secret") == 0) {
1594                         int len = os_strlen(pos);
1595                         if (len == 0) {
1596                                 /* RFC 2865, Ch. 3 */
1597                                 printf("Line %d: empty shared secret is not "
1598                                        "allowed.\n", line);
1599                                 errors++;
1600                         }
1601                         bss->radius->auth_server->shared_secret =
1602                                 (u8 *) os_strdup(pos);
1603                         bss->radius->auth_server->shared_secret_len = len;
1604                 } else if (os_strcmp(buf, "acct_server_addr") == 0) {
1605                         if (hostapd_config_read_radius_addr(
1606                                     &bss->radius->acct_servers,
1607                                     &bss->radius->num_acct_servers, pos, 1813,
1608                                     &bss->radius->acct_server)) {
1609                                 printf("Line %d: invalid IP address '%s'\n",
1610                                        line, pos);
1611                                 errors++;
1612                         }
1613                 } else if (bss->radius->acct_server &&
1614                            os_strcmp(buf, "acct_server_port") == 0) {
1615                         bss->radius->acct_server->port = atoi(pos);
1616                 } else if (bss->radius->acct_server &&
1617                            os_strcmp(buf, "acct_server_shared_secret") == 0) {
1618                         int len = os_strlen(pos);
1619                         if (len == 0) {
1620                                 /* RFC 2865, Ch. 3 */
1621                                 printf("Line %d: empty shared secret is not "
1622                                        "allowed.\n", line);
1623                                 errors++;
1624                         }
1625                         bss->radius->acct_server->shared_secret =
1626                                 (u8 *) os_strdup(pos);
1627                         bss->radius->acct_server->shared_secret_len = len;
1628                 } else if (os_strcmp(buf, "radius_retry_primary_interval") ==
1629                            0) {
1630                         bss->radius->retry_primary_interval = atoi(pos);
1631                 } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0)
1632                 {
1633                         bss->radius->acct_interim_interval = atoi(pos);
1634                 } else if (os_strcmp(buf, "auth_algs") == 0) {
1635                         bss->auth_algs = atoi(pos);
1636                         if (bss->auth_algs == 0) {
1637                                 printf("Line %d: no authentication algorithms "
1638                                        "allowed\n",
1639                                        line);
1640                                 errors++;
1641                         }
1642                 } else if (os_strcmp(buf, "max_num_sta") == 0) {
1643                         bss->max_num_sta = atoi(pos);
1644                         if (bss->max_num_sta < 0 ||
1645                             bss->max_num_sta > MAX_STA_COUNT) {
1646                                 printf("Line %d: Invalid max_num_sta=%d; "
1647                                        "allowed range 0..%d\n", line,
1648                                        bss->max_num_sta, MAX_STA_COUNT);
1649                                 errors++;
1650                         }
1651                 } else if (os_strcmp(buf, "wpa") == 0) {
1652                         bss->wpa = atoi(pos);
1653                 } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
1654                         bss->wpa_group_rekey = atoi(pos);
1655                 } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
1656                         bss->wpa_strict_rekey = atoi(pos);
1657                 } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
1658                         bss->wpa_gmk_rekey = atoi(pos);
1659                 } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
1660                         int len = os_strlen(pos);
1661                         if (len < 8 || len > 63) {
1662                                 printf("Line %d: invalid WPA passphrase length"
1663                                        " %d (expected 8..63)\n", line, len);
1664                                 errors++;
1665                         } else {
1666                                 os_free(bss->ssid.wpa_passphrase);
1667                                 bss->ssid.wpa_passphrase = os_strdup(pos);
1668                         }
1669                 } else if (os_strcmp(buf, "wpa_psk") == 0) {
1670                         os_free(bss->ssid.wpa_psk);
1671                         bss->ssid.wpa_psk =
1672                                 os_zalloc(sizeof(struct hostapd_wpa_psk));
1673                         if (bss->ssid.wpa_psk == NULL)
1674                                 errors++;
1675                         else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk,
1676                                             PMK_LEN) ||
1677                                  pos[PMK_LEN * 2] != '\0') {
1678                                 printf("Line %d: Invalid PSK '%s'.\n", line,
1679                                        pos);
1680                                 errors++;
1681                         } else {
1682                                 bss->ssid.wpa_psk->group = 1;
1683                         }
1684                 } else if (os_strcmp(buf, "wpa_psk_file") == 0) {
1685                         os_free(bss->ssid.wpa_psk_file);
1686                         bss->ssid.wpa_psk_file = os_strdup(pos);
1687                         if (!bss->ssid.wpa_psk_file) {
1688                                 printf("Line %d: allocation failed\n", line);
1689                                 errors++;
1690                         }
1691                 } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
1692                         bss->wpa_key_mgmt =
1693                                 hostapd_config_parse_key_mgmt(line, pos);
1694                         if (bss->wpa_key_mgmt == -1)
1695                                 errors++;
1696                 } else if (os_strcmp(buf, "wpa_pairwise") == 0) {
1697                         bss->wpa_pairwise =
1698                                 hostapd_config_parse_cipher(line, pos);
1699                         if (bss->wpa_pairwise == -1 ||
1700                             bss->wpa_pairwise == 0)
1701                                 errors++;
1702                         else if (bss->wpa_pairwise &
1703                                  (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
1704                                   WPA_CIPHER_WEP104)) {
1705                                 printf("Line %d: unsupported pairwise "
1706                                        "cipher suite '%s'\n",
1707                                        bss->wpa_pairwise, pos);
1708                                 errors++;
1709                         }
1710                 } else if (os_strcmp(buf, "rsn_pairwise") == 0) {
1711                         bss->rsn_pairwise =
1712                                 hostapd_config_parse_cipher(line, pos);
1713                         if (bss->rsn_pairwise == -1 ||
1714                             bss->rsn_pairwise == 0)
1715                                 errors++;
1716                         else if (bss->rsn_pairwise &
1717                                  (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
1718                                   WPA_CIPHER_WEP104)) {
1719                                 printf("Line %d: unsupported pairwise "
1720                                        "cipher suite '%s'\n",
1721                                        bss->rsn_pairwise, pos);
1722                                 errors++;
1723                         }
1724 #ifdef CONFIG_RSN_PREAUTH
1725                 } else if (os_strcmp(buf, "rsn_preauth") == 0) {
1726                         bss->rsn_preauth = atoi(pos);
1727                 } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
1728                         bss->rsn_preauth_interfaces = os_strdup(pos);
1729 #endif /* CONFIG_RSN_PREAUTH */
1730 #ifdef CONFIG_PEERKEY
1731                 } else if (os_strcmp(buf, "peerkey") == 0) {
1732                         bss->peerkey = atoi(pos);
1733 #endif /* CONFIG_PEERKEY */
1734 #ifdef CONFIG_IEEE80211R
1735                 } else if (os_strcmp(buf, "mobility_domain") == 0) {
1736                         if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
1737                             hexstr2bin(pos, bss->mobility_domain,
1738                                        MOBILITY_DOMAIN_ID_LEN) != 0) {
1739                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1740                                            "mobility_domain '%s'", line, pos);
1741                                 errors++;
1742                                 continue;
1743                         }
1744                 } else if (os_strcmp(buf, "r1_key_holder") == 0) {
1745                         if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
1746                             hexstr2bin(pos, bss->r1_key_holder,
1747                                        FT_R1KH_ID_LEN) != 0) {
1748                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1749                                            "r1_key_holder '%s'", line, pos);
1750                                 errors++;
1751                                 continue;
1752                         }
1753                 } else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
1754                         bss->r0_key_lifetime = atoi(pos);
1755                 } else if (os_strcmp(buf, "reassociation_deadline") == 0) {
1756                         bss->reassociation_deadline = atoi(pos);
1757                 } else if (os_strcmp(buf, "r0kh") == 0) {
1758                         if (add_r0kh(bss, pos) < 0) {
1759                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1760                                            "r0kh '%s'", line, pos);
1761                                 errors++;
1762                                 continue;
1763                         }
1764                 } else if (os_strcmp(buf, "r1kh") == 0) {
1765                         if (add_r1kh(bss, pos) < 0) {
1766                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid "
1767                                            "r1kh '%s'", line, pos);
1768                                 errors++;
1769                                 continue;
1770                         }
1771                 } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
1772                         bss->pmk_r1_push = atoi(pos);
1773 #endif /* CONFIG_IEEE80211R */
1774                 } else if (os_strcmp(buf, "ctrl_interface") == 0) {
1775                         os_free(bss->ctrl_interface);
1776                         bss->ctrl_interface = os_strdup(pos);
1777                 } else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
1778 #ifndef CONFIG_NATIVE_WINDOWS
1779                         struct group *grp;
1780                         char *endp;
1781                         const char *group = pos;
1782
1783                         grp = getgrnam(group);
1784                         if (grp) {
1785                                 bss->ctrl_interface_gid = grp->gr_gid;
1786                                 bss->ctrl_interface_gid_set = 1;
1787                                 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
1788                                            " (from group name '%s')",
1789                                            bss->ctrl_interface_gid, group);
1790                                 continue;
1791                         }
1792
1793                         /* Group name not found - try to parse this as gid */
1794                         bss->ctrl_interface_gid = strtol(group, &endp, 10);
1795                         if (*group == '\0' || *endp != '\0') {
1796                                 wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
1797                                            "'%s'", line, group);
1798                                 errors++;
1799                                 continue;
1800                         }
1801                         bss->ctrl_interface_gid_set = 1;
1802                         wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
1803                                    bss->ctrl_interface_gid);
1804 #endif /* CONFIG_NATIVE_WINDOWS */
1805 #ifdef RADIUS_SERVER
1806                 } else if (os_strcmp(buf, "radius_server_clients") == 0) {
1807                         os_free(bss->radius_server_clients);
1808                         bss->radius_server_clients = os_strdup(pos);
1809                 } else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
1810                         bss->radius_server_auth_port = atoi(pos);
1811                 } else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
1812                         bss->radius_server_ipv6 = atoi(pos);
1813 #endif /* RADIUS_SERVER */
1814                 } else if (os_strcmp(buf, "test_socket") == 0) {
1815                         os_free(bss->test_socket);
1816                         bss->test_socket = os_strdup(pos);
1817                 } else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
1818                         bss->use_pae_group_addr = atoi(pos);
1819                 } else if (os_strcmp(buf, "hw_mode") == 0) {
1820                         if (os_strcmp(pos, "a") == 0)
1821                                 conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
1822                         else if (os_strcmp(pos, "b") == 0)
1823                                 conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
1824                         else if (os_strcmp(pos, "g") == 0)
1825                                 conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
1826                         else {
1827                                 printf("Line %d: unknown hw_mode '%s'\n",
1828                                        line, pos);
1829                                 errors++;
1830                         }
1831                 } else if (os_strcmp(buf, "channel") == 0) {
1832                         conf->channel = atoi(pos);
1833                 } else if (os_strcmp(buf, "beacon_int") == 0) {
1834                         int val = atoi(pos);
1835                         /* MIB defines range as 1..65535, but very small values
1836                          * cause problems with the current implementation.
1837                          * Since it is unlikely that this small numbers are
1838                          * useful in real life scenarios, do not allow beacon
1839                          * period to be set below 15 TU. */
1840                         if (val < 15 || val > 65535) {
1841                                 printf("Line %d: invalid beacon_int %d "
1842                                        "(expected 15..65535)\n",
1843                                        line, val);
1844                                 errors++;
1845                         } else
1846                                 conf->beacon_int = val;
1847                 } else if (os_strcmp(buf, "dtim_period") == 0) {
1848                         bss->dtim_period = atoi(pos);
1849                         if (bss->dtim_period < 1 || bss->dtim_period > 255) {
1850                                 printf("Line %d: invalid dtim_period %d\n",
1851                                        line, bss->dtim_period);
1852                                 errors++;
1853                         }
1854                 } else if (os_strcmp(buf, "rts_threshold") == 0) {
1855                         conf->rts_threshold = atoi(pos);
1856                         if (conf->rts_threshold < 0 ||
1857                             conf->rts_threshold > 2347) {
1858                                 printf("Line %d: invalid rts_threshold %d\n",
1859                                        line, conf->rts_threshold);
1860                                 errors++;
1861                         }
1862                 } else if (os_strcmp(buf, "fragm_threshold") == 0) {
1863                         conf->fragm_threshold = atoi(pos);
1864                         if (conf->fragm_threshold < 256 ||
1865                             conf->fragm_threshold > 2346) {
1866                                 printf("Line %d: invalid fragm_threshold %d\n",
1867                                        line, conf->fragm_threshold);
1868                                 errors++;
1869                         }
1870                 } else if (os_strcmp(buf, "send_probe_response") == 0) {
1871                         int val = atoi(pos);
1872                         if (val != 0 && val != 1) {
1873                                 printf("Line %d: invalid send_probe_response "
1874                                        "%d (expected 0 or 1)\n", line, val);
1875                         } else
1876                                 conf->send_probe_response = val;
1877                 } else if (os_strcmp(buf, "supported_rates") == 0) {
1878                         if (hostapd_parse_rates(&conf->supported_rates, pos)) {
1879                                 printf("Line %d: invalid rate list\n", line);
1880                                 errors++;
1881                         }
1882                 } else if (os_strcmp(buf, "basic_rates") == 0) {
1883                         if (hostapd_parse_rates(&conf->basic_rates, pos)) {
1884                                 printf("Line %d: invalid rate list\n", line);
1885                                 errors++;
1886                         }
1887                 } else if (os_strcmp(buf, "preamble") == 0) {
1888                         if (atoi(pos))
1889                                 conf->preamble = SHORT_PREAMBLE;
1890                         else
1891                                 conf->preamble = LONG_PREAMBLE;
1892                 } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
1893                         bss->ignore_broadcast_ssid = atoi(pos);
1894                 } else if (os_strcmp(buf, "bridge_packets") == 0) {
1895                         conf->bridge_packets = atoi(pos);
1896                 } else if (os_strcmp(buf, "wep_default_key") == 0) {
1897                         bss->ssid.wep.idx = atoi(pos);
1898                         if (bss->ssid.wep.idx > 3) {
1899                                 printf("Invalid wep_default_key index %d\n",
1900                                        bss->ssid.wep.idx);
1901                                 errors++;
1902                         }
1903                 } else if (os_strcmp(buf, "wep_key0") == 0 ||
1904                            os_strcmp(buf, "wep_key1") == 0 ||
1905                            os_strcmp(buf, "wep_key2") == 0 ||
1906                            os_strcmp(buf, "wep_key3") == 0) {
1907                         if (hostapd_config_read_wep(&bss->ssid.wep,
1908                                                     buf[7] - '0', pos)) {
1909                                 printf("Line %d: invalid WEP key '%s'\n",
1910                                        line, buf);
1911                                 errors++;
1912                         }
1913                 } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
1914                         bss->ssid.dynamic_vlan = atoi(pos);
1915                 } else if (os_strcmp(buf, "vlan_file") == 0) {
1916                         if (hostapd_config_read_vlan_file(bss, pos)) {
1917                                 printf("Line %d: failed to read VLAN file "
1918                                        "'%s'\n", line, pos);
1919                                 errors++;
1920                         }
1921 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1922                 } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
1923                         bss->ssid.vlan_tagged_interface = os_strdup(pos);
1924 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1925                 } else if (os_strcmp(buf, "passive_scan_interval") == 0) {
1926                         conf->passive_scan_interval = atoi(pos);
1927                 } else if (os_strcmp(buf, "passive_scan_listen") == 0) {
1928                         conf->passive_scan_listen = atoi(pos);
1929                 } else if (os_strcmp(buf, "passive_scan_mode") == 0) {
1930                         conf->passive_scan_mode = atoi(pos);
1931                 } else if (os_strcmp(buf, "ap_table_max_size") == 0) {
1932                         conf->ap_table_max_size = atoi(pos);
1933                 } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
1934                         conf->ap_table_expiration_time = atoi(pos);
1935                 } else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
1936                         if (hostapd_config_tx_queue(conf, buf, pos)) {
1937                                 printf("Line %d: invalid TX queue item\n",
1938                                        line);
1939                                 errors++;
1940                         }
1941                 } else if (os_strcmp(buf, "wme_enabled") == 0) {
1942                         bss->wme_enabled = atoi(pos);
1943                 } else if (os_strncmp(buf, "wme_ac_", 7) == 0) {
1944                         if (hostapd_config_wme_ac(conf, buf, pos)) {
1945                                 printf("Line %d: invalid wme ac item\n",
1946                                        line);
1947                                 errors++;
1948                         }
1949                 } else if (os_strcmp(buf, "bss") == 0) {
1950                         if (hostapd_config_bss(conf, pos)) {
1951                                 printf("Line %d: invalid bss item\n", line);
1952                                 errors++;
1953                         }
1954                 } else if (os_strcmp(buf, "bssid") == 0) {
1955                         if (bss == conf->bss &&
1956                             (!conf->driver || !conf->driver->init_bssid)) {
1957                                 printf("Line %d: bssid item not allowed "
1958                                        "for the default interface and this "
1959                                        "driver\n", line);
1960                                 errors++;
1961                         } else if (hwaddr_aton(pos, bss->bssid)) {
1962                                 printf("Line %d: invalid bssid item\n", line);
1963                                 errors++;
1964                         }
1965 #ifdef CONFIG_IEEE80211W
1966                 } else if (os_strcmp(buf, "ieee80211w") == 0) {
1967                         bss->ieee80211w = atoi(pos);
1968 #endif /* CONFIG_IEEE80211W */
1969 #ifdef CONFIG_IEEE80211N
1970                 } else if (os_strcmp(buf, "ieee80211n") == 0) {
1971                         conf->ieee80211n = atoi(pos);
1972 #endif /* CONFIG_IEEE80211N */
1973                 } else if (os_strcmp(buf, "max_listen_interval") == 0) {
1974                         bss->max_listen_interval = atoi(pos);
1975                 } else if (os_strcmp(buf, "okc") == 0) {
1976                         bss->okc = atoi(pos);
1977                 } else {
1978                         printf("Line %d: unknown configuration item '%s'\n",
1979                                line, buf);
1980                         errors++;
1981                 }
1982         }
1983
1984         fclose(f);
1985
1986         if (bss->individual_wep_key_len == 0) {
1987                 /* individual keys are not use; can use key idx0 for broadcast
1988                  * keys */
1989                 bss->broadcast_key_idx_min = 0;
1990         }
1991
1992         /* Select group cipher based on the enabled pairwise cipher suites */
1993         pairwise = 0;
1994         if (bss->wpa & 1)
1995                 pairwise |= bss->wpa_pairwise;
1996         if (bss->wpa & 2) {
1997                 if (bss->rsn_pairwise == 0)
1998                         bss->rsn_pairwise = bss->wpa_pairwise;
1999                 pairwise |= bss->rsn_pairwise;
2000         }
2001         if (pairwise & WPA_CIPHER_TKIP)
2002                 bss->wpa_group = WPA_CIPHER_TKIP;
2003         else
2004                 bss->wpa_group = WPA_CIPHER_CCMP;
2005
2006         for (i = 0; i < conf->num_bss; i++) {
2007                 bss = &conf->bss[i];
2008
2009                 bss->radius->auth_server = bss->radius->auth_servers;
2010                 bss->radius->acct_server = bss->radius->acct_servers;
2011
2012                 if (bss->wpa && bss->ieee802_1x) {
2013                         bss->ssid.security_policy = SECURITY_WPA;
2014                 } else if (bss->wpa) {
2015                         bss->ssid.security_policy = SECURITY_WPA_PSK;
2016                 } else if (bss->ieee802_1x) {
2017                         bss->ssid.security_policy = SECURITY_IEEE_802_1X;
2018                         bss->ssid.wep.default_len = bss->default_wep_key_len;
2019                 } else if (bss->ssid.wep.keys_set)
2020                         bss->ssid.security_policy = SECURITY_STATIC_WEP;
2021                 else
2022                         bss->ssid.security_policy = SECURITY_PLAINTEXT;
2023         }
2024
2025         if (hostapd_config_check(conf))
2026                 errors++;
2027
2028         if (errors) {
2029                 printf("%d errors found in configuration file '%s'\n",
2030                        errors, fname);
2031                 hostapd_config_free(conf);
2032                 conf = NULL;
2033         }
2034
2035         return conf;
2036 }
2037
2038
2039 int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
2040 {
2041         int i;
2042
2043         if (a->idx != b->idx || a->default_len != b->default_len)
2044                 return 1;
2045         for (i = 0; i < NUM_WEP_KEYS; i++)
2046                 if (a->len[i] != b->len[i] ||
2047                     os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
2048                         return 1;
2049         return 0;
2050 }
2051
2052
2053 static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
2054                                        int num_servers)
2055 {
2056         int i;
2057
2058         for (i = 0; i < num_servers; i++) {
2059                 os_free(servers[i].shared_secret);
2060         }
2061         os_free(servers);
2062 }
2063
2064
2065 static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
2066 {
2067         os_free(user->identity);
2068         os_free(user->password);
2069         os_free(user);
2070 }
2071
2072
2073 static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
2074 {
2075         int i;
2076         for (i = 0; i < NUM_WEP_KEYS; i++) {
2077                 os_free(keys->key[i]);
2078                 keys->key[i] = NULL;
2079         }
2080 }
2081
2082
2083 static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
2084 {
2085         struct hostapd_wpa_psk *psk, *prev;
2086         struct hostapd_eap_user *user, *prev_user;
2087
2088         if (conf == NULL)
2089                 return;
2090
2091         psk = conf->ssid.wpa_psk;
2092         while (psk) {
2093                 prev = psk;
2094                 psk = psk->next;
2095                 os_free(prev);
2096         }
2097
2098         os_free(conf->ssid.wpa_passphrase);
2099         os_free(conf->ssid.wpa_psk_file);
2100 #ifdef CONFIG_FULL_DYNAMIC_VLAN
2101         os_free(conf->ssid.vlan_tagged_interface);
2102 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
2103
2104         user = conf->eap_user;
2105         while (user) {
2106                 prev_user = user;
2107                 user = user->next;
2108                 hostapd_config_free_eap_user(prev_user);
2109         }
2110
2111         os_free(conf->dump_log_name);
2112         os_free(conf->eap_req_id_text);
2113         os_free(conf->accept_mac);
2114         os_free(conf->deny_mac);
2115         os_free(conf->nas_identifier);
2116         hostapd_config_free_radius(conf->radius->auth_servers,
2117                                    conf->radius->num_auth_servers);
2118         hostapd_config_free_radius(conf->radius->acct_servers,
2119                                    conf->radius->num_acct_servers);
2120         os_free(conf->rsn_preauth_interfaces);
2121         os_free(conf->ctrl_interface);
2122         os_free(conf->ca_cert);
2123         os_free(conf->server_cert);
2124         os_free(conf->private_key);
2125         os_free(conf->private_key_passwd);
2126         os_free(conf->dh_file);
2127         os_free(conf->pac_opaque_encr_key);
2128         os_free(conf->eap_fast_a_id);
2129         os_free(conf->eap_sim_db);
2130         os_free(conf->radius_server_clients);
2131         os_free(conf->test_socket);
2132         os_free(conf->radius);
2133         hostapd_config_free_vlan(conf);
2134         if (conf->ssid.dyn_vlan_keys) {
2135                 struct hostapd_ssid *ssid = &conf->ssid;
2136                 size_t i;
2137                 for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
2138                         if (ssid->dyn_vlan_keys[i] == NULL)
2139                                 continue;
2140                         hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
2141                         os_free(ssid->dyn_vlan_keys[i]);
2142                 }
2143                 os_free(ssid->dyn_vlan_keys);
2144                 ssid->dyn_vlan_keys = NULL;
2145         }
2146
2147 #ifdef CONFIG_IEEE80211R
2148         {
2149                 struct ft_remote_r0kh *r0kh, *r0kh_prev;
2150                 struct ft_remote_r1kh *r1kh, *r1kh_prev;
2151
2152                 r0kh = conf->r0kh_list;
2153                 conf->r0kh_list = NULL;
2154                 while (r0kh) {
2155                         r0kh_prev = r0kh;
2156                         r0kh = r0kh->next;
2157                         os_free(r0kh_prev);
2158                 }
2159
2160                 r1kh = conf->r1kh_list;
2161                 conf->r1kh_list = NULL;
2162                 while (r1kh) {
2163                         r1kh_prev = r1kh;
2164                         r1kh = r1kh->next;
2165                         os_free(r1kh_prev);
2166                 }
2167         }
2168 #endif /* CONFIG_IEEE80211R */
2169 }
2170
2171
2172 void hostapd_config_free(struct hostapd_config *conf)
2173 {
2174         size_t i;
2175
2176         if (conf == NULL)
2177                 return;
2178
2179         for (i = 0; i < conf->num_bss; i++)
2180                 hostapd_config_free_bss(&conf->bss[i]);
2181         os_free(conf->bss);
2182
2183         os_free(conf);
2184 }
2185
2186
2187 /* Perform a binary search for given MAC address from a pre-sorted list.
2188  * Returns 1 if address is in the list or 0 if not. */
2189 int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
2190                           const u8 *addr, int *vlan_id)
2191 {
2192         int start, end, middle, res;
2193
2194         start = 0;
2195         end = num_entries - 1;
2196
2197         while (start <= end) {
2198                 middle = (start + end) / 2;
2199                 res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
2200                 if (res == 0) {
2201                         if (vlan_id)
2202                                 *vlan_id = list[middle].vlan_id;
2203                         return 1;
2204                 }
2205                 if (res < 0)
2206                         start = middle + 1;
2207                 else
2208                         end = middle - 1;
2209         }
2210
2211         return 0;
2212 }
2213
2214
2215 int hostapd_rate_found(int *list, int rate)
2216 {
2217         int i;
2218
2219         if (list == NULL)
2220                 return 0;
2221
2222         for (i = 0; list[i] >= 0; i++)
2223                 if (list[i] == rate)
2224                         return 1;
2225
2226         return 0;
2227 }
2228
2229
2230 const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
2231 {
2232         struct hostapd_vlan *v = vlan;
2233         while (v) {
2234                 if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
2235                         return v->ifname;
2236                 v = v->next;
2237         }
2238         return NULL;
2239 }
2240
2241
2242 const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
2243                            const u8 *addr, const u8 *prev_psk)
2244 {
2245         struct hostapd_wpa_psk *psk;
2246         int next_ok = prev_psk == NULL;
2247
2248         for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
2249                 if (next_ok &&
2250                     (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
2251                         return psk->psk;
2252
2253                 if (psk->psk == prev_psk)
2254                         next_ok = 1;
2255         }
2256
2257         return NULL;
2258 }
2259
2260
2261 const struct hostapd_eap_user *
2262 hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
2263                      size_t identity_len, int phase2)
2264 {
2265         struct hostapd_eap_user *user = conf->eap_user;
2266
2267         while (user) {
2268                 if (!phase2 && user->identity == NULL) {
2269                         /* Wildcard match */
2270                         break;
2271                 }
2272
2273                 if (user->phase2 == !!phase2 && user->wildcard_prefix &&
2274                     identity_len >= user->identity_len &&
2275                     os_memcmp(user->identity, identity, user->identity_len) ==
2276                     0) {
2277                         /* Wildcard prefix match */
2278                         break;
2279                 }
2280
2281                 if (user->phase2 == !!phase2 &&
2282                     user->identity_len == identity_len &&
2283                     os_memcmp(user->identity, identity, identity_len) == 0)
2284                         break;
2285                 user = user->next;
2286         }
2287
2288         return user;
2289 }