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