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