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