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