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