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