1/*
2 * hostapd / Configuration file parser
3 * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10#ifndef CONFIG_NATIVE_WINDOWS
11#include <grp.h>
12#endif /* CONFIG_NATIVE_WINDOWS */
13
14#include "utils/common.h"
15#include "utils/uuid.h"
16#include "common/ieee802_11_defs.h"
17#include "drivers/driver.h"
18#include "eap_server/eap.h"
19#include "radius/radius_client.h"
20#include "ap/wpa_auth.h"
21#include "ap/ap_config.h"
22#include "config_file.h"
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_array(*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	if (os_strncmp(fname, "sqlite:", 7) == 0) {
204		os_free(conf->eap_user_sqlite);
205		conf->eap_user_sqlite = os_strdup(fname + 7);
206		return 0;
207	}
208
209	f = fopen(fname, "r");
210	if (!f) {
211		wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname);
212		return -1;
213	}
214
215	/* Lines: "user" METHOD,METHOD2 "password" (password optional) */
216	while (fgets(buf, sizeof(buf), f)) {
217		line++;
218
219		if (buf[0] == '#')
220			continue;
221		pos = buf;
222		while (*pos != '\0') {
223			if (*pos == '\n') {
224				*pos = '\0';
225				break;
226			}
227			pos++;
228		}
229		if (buf[0] == '\0')
230			continue;
231
232		user = NULL;
233
234		if (buf[0] != '"' && buf[0] != '*') {
235			wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in "
236				   "start) on line %d in '%s'", line, fname);
237			goto failed;
238		}
239
240		user = os_zalloc(sizeof(*user));
241		if (user == NULL) {
242			wpa_printf(MSG_ERROR, "EAP user allocation failed");
243			goto failed;
244		}
245		user->force_version = -1;
246
247		if (buf[0] == '*') {
248			pos = buf;
249		} else {
250			pos = buf + 1;
251			start = pos;
252			while (*pos != '"' && *pos != '\0')
253				pos++;
254			if (*pos == '\0') {
255				wpa_printf(MSG_ERROR, "Invalid EAP identity "
256					   "(no \" in end) on line %d in '%s'",
257					   line, fname);
258				goto failed;
259			}
260
261			user->identity = os_malloc(pos - start);
262			if (user->identity == NULL) {
263				wpa_printf(MSG_ERROR, "Failed to allocate "
264					   "memory for EAP identity");
265				goto failed;
266			}
267			os_memcpy(user->identity, start, pos - start);
268			user->identity_len = pos - start;
269
270			if (pos[0] == '"' && pos[1] == '*') {
271				user->wildcard_prefix = 1;
272				pos++;
273			}
274		}
275		pos++;
276		while (*pos == ' ' || *pos == '\t')
277			pos++;
278
279		if (*pos == '\0') {
280			wpa_printf(MSG_ERROR, "No EAP method on line %d in "
281				   "'%s'", line, fname);
282			goto failed;
283		}
284
285		start = pos;
286		while (*pos != ' ' && *pos != '\t' && *pos != '\0')
287			pos++;
288		if (*pos == '\0') {
289			pos = NULL;
290		} else {
291			*pos = '\0';
292			pos++;
293		}
294		num_methods = 0;
295		while (*start) {
296			char *pos3 = os_strchr(start, ',');
297			if (pos3) {
298				*pos3++ = '\0';
299			}
300			user->methods[num_methods].method =
301				eap_server_get_type(
302					start,
303					&user->methods[num_methods].vendor);
304			if (user->methods[num_methods].vendor ==
305			    EAP_VENDOR_IETF &&
306			    user->methods[num_methods].method == EAP_TYPE_NONE)
307			{
308				if (os_strcmp(start, "TTLS-PAP") == 0) {
309					user->ttls_auth |= EAP_TTLS_AUTH_PAP;
310					goto skip_eap;
311				}
312				if (os_strcmp(start, "TTLS-CHAP") == 0) {
313					user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
314					goto skip_eap;
315				}
316				if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
317					user->ttls_auth |=
318						EAP_TTLS_AUTH_MSCHAP;
319					goto skip_eap;
320				}
321				if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
322					user->ttls_auth |=
323						EAP_TTLS_AUTH_MSCHAPV2;
324					goto skip_eap;
325				}
326				wpa_printf(MSG_ERROR, "Unsupported EAP type "
327					   "'%s' on line %d in '%s'",
328					   start, line, fname);
329				goto failed;
330			}
331
332			num_methods++;
333			if (num_methods >= EAP_MAX_METHODS)
334				break;
335		skip_eap:
336			if (pos3 == NULL)
337				break;
338			start = pos3;
339		}
340		if (num_methods == 0 && user->ttls_auth == 0) {
341			wpa_printf(MSG_ERROR, "No EAP types configured on "
342				   "line %d in '%s'", line, fname);
343			goto failed;
344		}
345
346		if (pos == NULL)
347			goto done;
348
349		while (*pos == ' ' || *pos == '\t')
350			pos++;
351		if (*pos == '\0')
352			goto done;
353
354		if (os_strncmp(pos, "[ver=0]", 7) == 0) {
355			user->force_version = 0;
356			goto done;
357		}
358
359		if (os_strncmp(pos, "[ver=1]", 7) == 0) {
360			user->force_version = 1;
361			goto done;
362		}
363
364		if (os_strncmp(pos, "[2]", 3) == 0) {
365			user->phase2 = 1;
366			goto done;
367		}
368
369		if (*pos == '"') {
370			pos++;
371			start = pos;
372			while (*pos != '"' && *pos != '\0')
373				pos++;
374			if (*pos == '\0') {
375				wpa_printf(MSG_ERROR, "Invalid EAP password "
376					   "(no \" in end) on line %d in '%s'",
377					   line, fname);
378				goto failed;
379			}
380
381			user->password = os_malloc(pos - start);
382			if (user->password == NULL) {
383				wpa_printf(MSG_ERROR, "Failed to allocate "
384					   "memory for EAP password");
385				goto failed;
386			}
387			os_memcpy(user->password, start, pos - start);
388			user->password_len = pos - start;
389
390			pos++;
391		} else if (os_strncmp(pos, "hash:", 5) == 0) {
392			pos += 5;
393			pos2 = pos;
394			while (*pos2 != '\0' && *pos2 != ' ' &&
395			       *pos2 != '\t' && *pos2 != '#')
396				pos2++;
397			if (pos2 - pos != 32) {
398				wpa_printf(MSG_ERROR, "Invalid password hash "
399					   "on line %d in '%s'", line, fname);
400				goto failed;
401			}
402			user->password = os_malloc(16);
403			if (user->password == NULL) {
404				wpa_printf(MSG_ERROR, "Failed to allocate "
405					   "memory for EAP password hash");
406				goto failed;
407			}
408			if (hexstr2bin(pos, user->password, 16) < 0) {
409				wpa_printf(MSG_ERROR, "Invalid hash password "
410					   "on line %d in '%s'", line, fname);
411				goto failed;
412			}
413			user->password_len = 16;
414			user->password_hash = 1;
415			pos = pos2;
416		} else {
417			pos2 = pos;
418			while (*pos2 != '\0' && *pos2 != ' ' &&
419			       *pos2 != '\t' && *pos2 != '#')
420				pos2++;
421			if ((pos2 - pos) & 1) {
422				wpa_printf(MSG_ERROR, "Invalid hex password "
423					   "on line %d in '%s'", line, fname);
424				goto failed;
425			}
426			user->password = os_malloc((pos2 - pos) / 2);
427			if (user->password == NULL) {
428				wpa_printf(MSG_ERROR, "Failed to allocate "
429					   "memory for EAP password");
430				goto failed;
431			}
432			if (hexstr2bin(pos, user->password,
433				       (pos2 - pos) / 2) < 0) {
434				wpa_printf(MSG_ERROR, "Invalid hex password "
435					   "on line %d in '%s'", line, fname);
436				goto failed;
437			}
438			user->password_len = (pos2 - pos) / 2;
439			pos = pos2;
440		}
441
442		while (*pos == ' ' || *pos == '\t')
443			pos++;
444		if (os_strncmp(pos, "[2]", 3) == 0) {
445			user->phase2 = 1;
446		}
447
448	done:
449		if (tail == NULL) {
450			tail = conf->eap_user = user;
451		} else {
452			tail->next = user;
453			tail = user;
454		}
455		continue;
456
457	failed:
458		if (user) {
459			os_free(user->password);
460			os_free(user->identity);
461			os_free(user);
462		}
463		ret = -1;
464		break;
465	}
466
467	fclose(f);
468
469	return ret;
470}
471#endif /* EAP_SERVER */
472
473
474#ifndef CONFIG_NO_RADIUS
475static int
476hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
477				int *num_server, const char *val, int def_port,
478				struct hostapd_radius_server **curr_serv)
479{
480	struct hostapd_radius_server *nserv;
481	int ret;
482	static int server_index = 1;
483
484	nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv));
485	if (nserv == NULL)
486		return -1;
487
488	*server = nserv;
489	nserv = &nserv[*num_server];
490	(*num_server)++;
491	(*curr_serv) = nserv;
492
493	os_memset(nserv, 0, sizeof(*nserv));
494	nserv->port = def_port;
495	ret = hostapd_parse_ip_addr(val, &nserv->addr);
496	nserv->index = server_index++;
497
498	return ret;
499}
500
501
502static struct hostapd_radius_attr *
503hostapd_parse_radius_attr(const char *value)
504{
505	const char *pos;
506	char syntax;
507	struct hostapd_radius_attr *attr;
508	size_t len;
509
510	attr = os_zalloc(sizeof(*attr));
511	if (attr == NULL)
512		return NULL;
513
514	attr->type = atoi(value);
515
516	pos = os_strchr(value, ':');
517	if (pos == NULL) {
518		attr->val = wpabuf_alloc(1);
519		if (attr->val == NULL) {
520			os_free(attr);
521			return NULL;
522		}
523		wpabuf_put_u8(attr->val, 0);
524		return attr;
525	}
526
527	pos++;
528	if (pos[0] == '\0' || pos[1] != ':') {
529		os_free(attr);
530		return NULL;
531	}
532	syntax = *pos++;
533	pos++;
534
535	switch (syntax) {
536	case 's':
537		attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
538		break;
539	case 'x':
540		len = os_strlen(pos);
541		if (len & 1)
542			break;
543		len /= 2;
544		attr->val = wpabuf_alloc(len);
545		if (attr->val == NULL)
546			break;
547		if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
548			wpabuf_free(attr->val);
549			os_free(attr);
550			return NULL;
551		}
552		break;
553	case 'd':
554		attr->val = wpabuf_alloc(4);
555		if (attr->val)
556			wpabuf_put_be32(attr->val, atoi(pos));
557		break;
558	default:
559		os_free(attr);
560		return NULL;
561	}
562
563	if (attr->val == NULL) {
564		os_free(attr);
565		return NULL;
566	}
567
568	return attr;
569}
570
571
572static int hostapd_parse_das_client(struct hostapd_bss_config *bss,
573				    const char *val)
574{
575	char *secret;
576
577	secret = os_strchr(val, ' ');
578	if (secret == NULL)
579		return -1;
580
581	secret++;
582
583	if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
584		return -1;
585
586	os_free(bss->radius_das_shared_secret);
587	bss->radius_das_shared_secret = (u8 *) os_strdup(secret);
588	if (bss->radius_das_shared_secret == NULL)
589		return -1;
590	bss->radius_das_shared_secret_len = os_strlen(secret);
591
592	return 0;
593}
594#endif /* CONFIG_NO_RADIUS */
595
596
597static int hostapd_config_parse_key_mgmt(int line, const char *value)
598{
599	int val = 0, last;
600	char *start, *end, *buf;
601
602	buf = os_strdup(value);
603	if (buf == NULL)
604		return -1;
605	start = buf;
606
607	while (*start != '\0') {
608		while (*start == ' ' || *start == '\t')
609			start++;
610		if (*start == '\0')
611			break;
612		end = start;
613		while (*end != ' ' && *end != '\t' && *end != '\0')
614			end++;
615		last = *end == '\0';
616		*end = '\0';
617		if (os_strcmp(start, "WPA-PSK") == 0)
618			val |= WPA_KEY_MGMT_PSK;
619		else if (os_strcmp(start, "WPA-EAP") == 0)
620			val |= WPA_KEY_MGMT_IEEE8021X;
621#ifdef CONFIG_IEEE80211R
622		else if (os_strcmp(start, "FT-PSK") == 0)
623			val |= WPA_KEY_MGMT_FT_PSK;
624		else if (os_strcmp(start, "FT-EAP") == 0)
625			val |= WPA_KEY_MGMT_FT_IEEE8021X;
626#endif /* CONFIG_IEEE80211R */
627#ifdef CONFIG_IEEE80211W
628		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
629			val |= WPA_KEY_MGMT_PSK_SHA256;
630		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
631			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
632#endif /* CONFIG_IEEE80211W */
633#ifdef CONFIG_SAE
634		else if (os_strcmp(start, "SAE") == 0)
635			val |= WPA_KEY_MGMT_SAE;
636		else if (os_strcmp(start, "FT-SAE") == 0)
637			val |= WPA_KEY_MGMT_FT_SAE;
638#endif /* CONFIG_SAE */
639		else {
640			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
641				   line, start);
642			os_free(buf);
643			return -1;
644		}
645
646		if (last)
647			break;
648		start = end + 1;
649	}
650
651	os_free(buf);
652	if (val == 0) {
653		wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values "
654			   "configured.", line);
655		return -1;
656	}
657
658	return val;
659}
660
661
662static int hostapd_config_parse_cipher(int line, const char *value)
663{
664	int val = 0, last;
665	char *start, *end, *buf;
666
667	buf = os_strdup(value);
668	if (buf == NULL)
669		return -1;
670	start = buf;
671
672	while (*start != '\0') {
673		while (*start == ' ' || *start == '\t')
674			start++;
675		if (*start == '\0')
676			break;
677		end = start;
678		while (*end != ' ' && *end != '\t' && *end != '\0')
679			end++;
680		last = *end == '\0';
681		*end = '\0';
682		if (os_strcmp(start, "CCMP") == 0)
683			val |= WPA_CIPHER_CCMP;
684		else if (os_strcmp(start, "GCMP") == 0)
685			val |= WPA_CIPHER_GCMP;
686		else if (os_strcmp(start, "TKIP") == 0)
687			val |= WPA_CIPHER_TKIP;
688		else if (os_strcmp(start, "WEP104") == 0)
689			val |= WPA_CIPHER_WEP104;
690		else if (os_strcmp(start, "WEP40") == 0)
691			val |= WPA_CIPHER_WEP40;
692		else if (os_strcmp(start, "NONE") == 0)
693			val |= WPA_CIPHER_NONE;
694		else {
695			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
696				   line, start);
697			os_free(buf);
698			return -1;
699		}
700
701		if (last)
702			break;
703		start = end + 1;
704	}
705	os_free(buf);
706
707	if (val == 0) {
708		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
709			   line);
710		return -1;
711	}
712	return val;
713}
714
715
716static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
717				   char *val)
718{
719	size_t len = os_strlen(val);
720
721	if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL)
722		return -1;
723
724	if (val[0] == '"') {
725		if (len < 2 || val[len - 1] != '"')
726			return -1;
727		len -= 2;
728		wep->key[keyidx] = os_malloc(len);
729		if (wep->key[keyidx] == NULL)
730			return -1;
731		os_memcpy(wep->key[keyidx], val + 1, len);
732		wep->len[keyidx] = len;
733	} else {
734		if (len & 1)
735			return -1;
736		len /= 2;
737		wep->key[keyidx] = os_malloc(len);
738		if (wep->key[keyidx] == NULL)
739			return -1;
740		wep->len[keyidx] = len;
741		if (hexstr2bin(val, wep->key[keyidx], len) < 0)
742			return -1;
743	}
744
745	wep->keys_set++;
746
747	return 0;
748}
749
750
751static int hostapd_parse_rates(int **rate_list, char *val)
752{
753	int *list;
754	int count;
755	char *pos, *end;
756
757	os_free(*rate_list);
758	*rate_list = NULL;
759
760	pos = val;
761	count = 0;
762	while (*pos != '\0') {
763		if (*pos == ' ')
764			count++;
765		pos++;
766	}
767
768	list = os_malloc(sizeof(int) * (count + 2));
769	if (list == NULL)
770		return -1;
771	pos = val;
772	count = 0;
773	while (*pos != '\0') {
774		end = os_strchr(pos, ' ');
775		if (end)
776			*end = '\0';
777
778		list[count++] = atoi(pos);
779		if (!end)
780			break;
781		pos = end + 1;
782	}
783	list[count] = -1;
784
785	*rate_list = list;
786	return 0;
787}
788
789
790static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
791{
792	struct hostapd_bss_config *bss;
793
794	if (*ifname == '\0')
795		return -1;
796
797	bss = os_realloc_array(conf->bss, conf->num_bss + 1,
798			       sizeof(struct hostapd_bss_config));
799	if (bss == NULL) {
800		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
801			   "multi-BSS entry");
802		return -1;
803	}
804	conf->bss = bss;
805
806	bss = &(conf->bss[conf->num_bss]);
807	os_memset(bss, 0, sizeof(*bss));
808	bss->radius = os_zalloc(sizeof(*bss->radius));
809	if (bss->radius == NULL) {
810		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
811			   "multi-BSS RADIUS data");
812		return -1;
813	}
814
815	conf->num_bss++;
816	conf->last_bss = bss;
817
818	hostapd_config_defaults_bss(bss);
819	os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
820	os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
821
822	return 0;
823}
824
825
826/* convert floats with one decimal place to value*10 int, i.e.,
827 * "1.5" will return 15 */
828static int hostapd_config_read_int10(const char *value)
829{
830	int i, d;
831	char *pos;
832
833	i = atoi(value);
834	pos = os_strchr(value, '.');
835	d = 0;
836	if (pos) {
837		pos++;
838		if (*pos >= '0' && *pos <= '9')
839			d = *pos - '0';
840	}
841
842	return i * 10 + d;
843}
844
845
846static int valid_cw(int cw)
847{
848	return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
849		cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023);
850}
851
852
853enum {
854	IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
855	IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
856	IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
857	IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
858};
859
860static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
861				   char *val)
862{
863	int num;
864	char *pos;
865	struct hostapd_tx_queue_params *queue;
866
867	/* skip 'tx_queue_' prefix */
868	pos = name + 9;
869	if (os_strncmp(pos, "data", 4) == 0 &&
870	    pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
871		num = pos[4] - '0';
872		pos += 6;
873	} else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
874		   os_strncmp(pos, "beacon_", 7) == 0) {
875		wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
876		return 0;
877	} else {
878		wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
879		return -1;
880	}
881
882	if (num >= NUM_TX_QUEUES) {
883		/* for backwards compatibility, do not trigger failure */
884		wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
885		return 0;
886	}
887
888	queue = &conf->tx_queue[num];
889
890	if (os_strcmp(pos, "aifs") == 0) {
891		queue->aifs = atoi(val);
892		if (queue->aifs < 0 || queue->aifs > 255) {
893			wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
894				   queue->aifs);
895			return -1;
896		}
897	} else if (os_strcmp(pos, "cwmin") == 0) {
898		queue->cwmin = atoi(val);
899		if (!valid_cw(queue->cwmin)) {
900			wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
901				   queue->cwmin);
902			return -1;
903		}
904	} else if (os_strcmp(pos, "cwmax") == 0) {
905		queue->cwmax = atoi(val);
906		if (!valid_cw(queue->cwmax)) {
907			wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
908				   queue->cwmax);
909			return -1;
910		}
911	} else if (os_strcmp(pos, "burst") == 0) {
912		queue->burst = hostapd_config_read_int10(val);
913	} else {
914		wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
915		return -1;
916	}
917
918	return 0;
919}
920
921
922#ifdef CONFIG_IEEE80211R
923static int add_r0kh(struct hostapd_bss_config *bss, char *value)
924{
925	struct ft_remote_r0kh *r0kh;
926	char *pos, *next;
927
928	r0kh = os_zalloc(sizeof(*r0kh));
929	if (r0kh == NULL)
930		return -1;
931
932	/* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
933	pos = value;
934	next = os_strchr(pos, ' ');
935	if (next)
936		*next++ = '\0';
937	if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
938		wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos);
939		os_free(r0kh);
940		return -1;
941	}
942
943	pos = next;
944	next = os_strchr(pos, ' ');
945	if (next)
946		*next++ = '\0';
947	if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
948		wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos);
949		os_free(r0kh);
950		return -1;
951	}
952	r0kh->id_len = next - pos - 1;
953	os_memcpy(r0kh->id, pos, r0kh->id_len);
954
955	pos = next;
956	if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) {
957		wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos);
958		os_free(r0kh);
959		return -1;
960	}
961
962	r0kh->next = bss->r0kh_list;
963	bss->r0kh_list = r0kh;
964
965	return 0;
966}
967
968
969static int add_r1kh(struct hostapd_bss_config *bss, char *value)
970{
971	struct ft_remote_r1kh *r1kh;
972	char *pos, *next;
973
974	r1kh = os_zalloc(sizeof(*r1kh));
975	if (r1kh == NULL)
976		return -1;
977
978	/* 02:01:02:03:04:05 02:01:02:03:04:05
979	 * 000102030405060708090a0b0c0d0e0f */
980	pos = value;
981	next = os_strchr(pos, ' ');
982	if (next)
983		*next++ = '\0';
984	if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
985		wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos);
986		os_free(r1kh);
987		return -1;
988	}
989
990	pos = next;
991	next = os_strchr(pos, ' ');
992	if (next)
993		*next++ = '\0';
994	if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
995		wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos);
996		os_free(r1kh);
997		return -1;
998	}
999
1000	pos = next;
1001	if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) {
1002		wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos);
1003		os_free(r1kh);
1004		return -1;
1005	}
1006
1007	r1kh->next = bss->r1kh_list;
1008	bss->r1kh_list = r1kh;
1009
1010	return 0;
1011}
1012#endif /* CONFIG_IEEE80211R */
1013
1014
1015#ifdef CONFIG_IEEE80211N
1016static int hostapd_config_ht_capab(struct hostapd_config *conf,
1017				   const char *capab)
1018{
1019	if (os_strstr(capab, "[LDPC]"))
1020		conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
1021	if (os_strstr(capab, "[HT40-]")) {
1022		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1023		conf->secondary_channel = -1;
1024	}
1025	if (os_strstr(capab, "[HT40+]")) {
1026		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1027		conf->secondary_channel = 1;
1028	}
1029	if (os_strstr(capab, "[SMPS-STATIC]")) {
1030		conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
1031		conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
1032	}
1033	if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
1034		conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
1035		conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
1036	}
1037	if (os_strstr(capab, "[GF]"))
1038		conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
1039	if (os_strstr(capab, "[SHORT-GI-20]"))
1040		conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
1041	if (os_strstr(capab, "[SHORT-GI-40]"))
1042		conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
1043	if (os_strstr(capab, "[TX-STBC]"))
1044		conf->ht_capab |= HT_CAP_INFO_TX_STBC;
1045	if (os_strstr(capab, "[RX-STBC1]")) {
1046		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1047		conf->ht_capab |= HT_CAP_INFO_RX_STBC_1;
1048	}
1049	if (os_strstr(capab, "[RX-STBC12]")) {
1050		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1051		conf->ht_capab |= HT_CAP_INFO_RX_STBC_12;
1052	}
1053	if (os_strstr(capab, "[RX-STBC123]")) {
1054		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1055		conf->ht_capab |= HT_CAP_INFO_RX_STBC_123;
1056	}
1057	if (os_strstr(capab, "[DELAYED-BA]"))
1058		conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
1059	if (os_strstr(capab, "[MAX-AMSDU-7935]"))
1060		conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
1061	if (os_strstr(capab, "[DSSS_CCK-40]"))
1062		conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
1063	if (os_strstr(capab, "[PSMP]"))
1064		conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP;
1065	if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
1066		conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
1067
1068	return 0;
1069}
1070#endif /* CONFIG_IEEE80211N */
1071
1072
1073#ifdef CONFIG_IEEE80211AC
1074static int hostapd_config_vht_capab(struct hostapd_config *conf,
1075				    const char *capab)
1076{
1077	if (os_strstr(capab, "[MAX-MPDU-7991]"))
1078		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
1079	if (os_strstr(capab, "[MAX-MPDU-11454]"))
1080		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
1081	if (os_strstr(capab, "[VHT160]"))
1082		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1083	if (os_strstr(capab, "[VHT160-80PLUS80]"))
1084		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1085	if (os_strstr(capab, "[VHT160-80PLUS80]"))
1086		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1087	if (os_strstr(capab, "[RXLDPC]"))
1088		conf->vht_capab |= VHT_CAP_RXLDPC;
1089	if (os_strstr(capab, "[SHORT-GI-80]"))
1090		conf->vht_capab |= VHT_CAP_SHORT_GI_80;
1091	if (os_strstr(capab, "[SHORT-GI-160]"))
1092		conf->vht_capab |= VHT_CAP_SHORT_GI_160;
1093	if (os_strstr(capab, "[TX-STBC-2BY1]"))
1094		conf->vht_capab |= VHT_CAP_TXSTBC;
1095	if (os_strstr(capab, "[RX-STBC-1]"))
1096		conf->vht_capab |= VHT_CAP_RXSTBC_1;
1097	if (os_strstr(capab, "[RX-STBC-12]"))
1098		conf->vht_capab |= VHT_CAP_RXSTBC_2;
1099	if (os_strstr(capab, "[RX-STBC-123]"))
1100		conf->vht_capab |= VHT_CAP_RXSTBC_3;
1101	if (os_strstr(capab, "[RX-STBC-1234]"))
1102		conf->vht_capab |= VHT_CAP_RXSTBC_4;
1103	if (os_strstr(capab, "[SU-BEAMFORMER]"))
1104		conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
1105	if (os_strstr(capab, "[SU-BEAMFORMEE]"))
1106		conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1107	if (os_strstr(capab, "[BF-ANTENNA-2]") &&
1108	    (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
1109		conf->vht_capab |= VHT_CAP_BEAMFORMER_ANTENNAS_MAX;
1110	if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
1111	    (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
1112		conf->vht_capab |= VHT_CAP_SOUNDING_DIMENTION_MAX;
1113	if (os_strstr(capab, "[MU-BEAMFORMER]"))
1114		conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
1115	if (os_strstr(capab, "[MU-BEAMFORMEE]"))
1116		conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1117	if (os_strstr(capab, "[VHT-TXOP-PS]"))
1118		conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
1119	if (os_strstr(capab, "[HTC-VHT]"))
1120		conf->vht_capab |= VHT_CAP_HTC_VHT;
1121	if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP0]"))
1122		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT;
1123	if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
1124	    (conf->vht_capab & VHT_CAP_HTC_VHT))
1125		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
1126	if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
1127	    (conf->vht_capab & VHT_CAP_HTC_VHT))
1128		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
1129	if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
1130		conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
1131	if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
1132		conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
1133	return 0;
1134}
1135#endif /* CONFIG_IEEE80211AC */
1136
1137
1138static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
1139				    struct hostapd_config *conf)
1140{
1141	if (bss->ieee802_1x && !bss->eap_server &&
1142	    !bss->radius->auth_servers) {
1143		wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
1144			   "EAP authenticator configured).");
1145		return -1;
1146	}
1147
1148	if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
1149	    bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1150		wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
1151			   "RADIUS checking (macaddr_acl=2) enabled.");
1152		return -1;
1153	}
1154
1155	if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
1156	    bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
1157	    bss->ssid.wpa_psk_file == NULL &&
1158	    (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
1159	     bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
1160		wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
1161			   "is not configured.");
1162		return -1;
1163	}
1164
1165	if (hostapd_mac_comp_empty(bss->bssid) != 0) {
1166		size_t i;
1167
1168		for (i = 0; i < conf->num_bss; i++) {
1169			if ((&conf->bss[i] != bss) &&
1170			    (hostapd_mac_comp(conf->bss[i].bssid,
1171					      bss->bssid) == 0)) {
1172				wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
1173					   " on interface '%s' and '%s'.",
1174					   MAC2STR(bss->bssid),
1175					   conf->bss[i].iface, bss->iface);
1176				return -1;
1177			}
1178		}
1179	}
1180
1181#ifdef CONFIG_IEEE80211R
1182	if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
1183	    (bss->nas_identifier == NULL ||
1184	     os_strlen(bss->nas_identifier) < 1 ||
1185	     os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
1186		wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires "
1187			   "nas_identifier to be configured as a 1..48 octet "
1188			   "string");
1189		return -1;
1190	}
1191#endif /* CONFIG_IEEE80211R */
1192
1193#ifdef CONFIG_IEEE80211N
1194	if (conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
1195		bss->disable_11n = 1;
1196		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
1197			   "allowed, disabling HT capabilites");
1198	}
1199
1200	if (conf->ieee80211n &&
1201	    bss->ssid.security_policy == SECURITY_STATIC_WEP) {
1202		bss->disable_11n = 1;
1203		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
1204			   "allowed, disabling HT capabilities");
1205	}
1206
1207	if (conf->ieee80211n && bss->wpa &&
1208	    !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
1209	    !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))) {
1210		bss->disable_11n = 1;
1211		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
1212			   "requires CCMP/GCMP to be enabled, disabling HT "
1213			   "capabilities");
1214	}
1215#endif /* CONFIG_IEEE80211N */
1216
1217#ifdef CONFIG_WPS2
1218	if (bss->wps_state && bss->ignore_broadcast_ssid) {
1219		wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
1220			   "configuration forced WPS to be disabled");
1221		bss->wps_state = 0;
1222	}
1223
1224	if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) {
1225		wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
1226			   "disabled");
1227		bss->wps_state = 0;
1228	}
1229
1230	if (bss->wps_state && bss->wpa &&
1231	    (!(bss->wpa & 2) ||
1232	     !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) {
1233		wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
1234			   "WPA2/CCMP forced WPS to be disabled");
1235		bss->wps_state = 0;
1236	}
1237#endif /* CONFIG_WPS2 */
1238
1239#ifdef CONFIG_HS20
1240	if (bss->hs20 &&
1241	    (!(bss->wpa & 2) ||
1242	     !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) {
1243		wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
1244			   "configuration is required for Hotspot 2.0 "
1245			   "functionality");
1246		return -1;
1247	}
1248#endif /* CONFIG_HS20 */
1249
1250	return 0;
1251}
1252
1253
1254static int hostapd_config_check(struct hostapd_config *conf)
1255{
1256	size_t i;
1257
1258	if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) {
1259		wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
1260			   "setting the country_code");
1261		return -1;
1262	}
1263
1264	for (i = 0; i < conf->num_bss; i++) {
1265		if (hostapd_config_check_bss(&conf->bss[i], conf))
1266			return -1;
1267	}
1268
1269	return 0;
1270}
1271
1272
1273#ifdef CONFIG_INTERWORKING
1274static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
1275				    int line)
1276{
1277	size_t len = os_strlen(pos);
1278	u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
1279
1280	struct hostapd_roaming_consortium *rc;
1281
1282	if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
1283	    hexstr2bin(pos, oi, len / 2)) {
1284		wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
1285			   "'%s'", line, pos);
1286		return -1;
1287	}
1288	len /= 2;
1289
1290	rc = os_realloc_array(bss->roaming_consortium,
1291			      bss->roaming_consortium_count + 1,
1292			      sizeof(struct hostapd_roaming_consortium));
1293	if (rc == NULL)
1294		return -1;
1295
1296	os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
1297	rc[bss->roaming_consortium_count].len = len;
1298
1299	bss->roaming_consortium = rc;
1300	bss->roaming_consortium_count++;
1301
1302	return 0;
1303}
1304
1305
1306static int parse_lang_string(struct hostapd_lang_string **array,
1307			     unsigned int *count, char *pos)
1308{
1309	char *sep;
1310	size_t clen, nlen;
1311	struct hostapd_lang_string *ls;
1312
1313	sep = os_strchr(pos, ':');
1314	if (sep == NULL)
1315		return -1;
1316	*sep++ = '\0';
1317
1318	clen = os_strlen(pos);
1319	if (clen < 2)
1320		return -1;
1321	nlen = os_strlen(sep);
1322	if (nlen > 252)
1323		return -1;
1324
1325	ls = os_realloc_array(*array, *count + 1,
1326			      sizeof(struct hostapd_lang_string));
1327	if (ls == NULL)
1328		return -1;
1329
1330	*array = ls;
1331	ls = &(*array)[*count];
1332	(*count)++;
1333
1334	os_memset(ls->lang, 0, sizeof(ls->lang));
1335	os_memcpy(ls->lang, pos, clen);
1336	ls->name_len = nlen;
1337	os_memcpy(ls->name, sep, nlen);
1338
1339	return 0;
1340}
1341
1342
1343static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
1344			    int line)
1345{
1346	if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) {
1347		wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
1348			   line, pos);
1349		return -1;
1350	}
1351	return 0;
1352}
1353
1354
1355static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
1356			       int line)
1357{
1358	size_t count;
1359	char *pos;
1360	u8 *info = NULL, *ipos;
1361
1362	/* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
1363
1364	count = 1;
1365	for (pos = buf; *pos; pos++) {
1366		if ((*pos < '0' && *pos > '9') && *pos != ';' && *pos != ',')
1367			goto fail;
1368		if (*pos == ';')
1369			count++;
1370	}
1371	if (1 + count * 3 > 0x7f)
1372		goto fail;
1373
1374	info = os_zalloc(2 + 3 + count * 3);
1375	if (info == NULL)
1376		return -1;
1377
1378	ipos = info;
1379	*ipos++ = 0; /* GUD - Version 1 */
1380	*ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
1381	*ipos++ = 0; /* PLMN List IEI */
1382	/* ext(b8) | Length of PLMN List value contents(b7..1) */
1383	*ipos++ = 1 + count * 3;
1384	*ipos++ = count; /* Number of PLMNs */
1385
1386	pos = buf;
1387	while (pos && *pos) {
1388		char *mcc, *mnc;
1389		size_t mnc_len;
1390
1391		mcc = pos;
1392		mnc = os_strchr(pos, ',');
1393		if (mnc == NULL)
1394			goto fail;
1395		*mnc++ = '\0';
1396		pos = os_strchr(mnc, ';');
1397		if (pos)
1398			*pos++ = '\0';
1399
1400		mnc_len = os_strlen(mnc);
1401		if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3))
1402			goto fail;
1403
1404		/* BC coded MCC,MNC */
1405		/* MCC digit 2 | MCC digit 1 */
1406		*ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
1407		/* MNC digit 3 | MCC digit 3 */
1408		*ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
1409			(mcc[2] - '0');
1410		/* MNC digit 2 | MNC digit 1 */
1411		*ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
1412	}
1413
1414	os_free(bss->anqp_3gpp_cell_net);
1415	bss->anqp_3gpp_cell_net = info;
1416	bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
1417	wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
1418		    bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
1419
1420	return 0;
1421
1422fail:
1423	wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s",
1424		   line, buf);
1425	os_free(info);
1426	return -1;
1427}
1428
1429
1430static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line)
1431{
1432	struct hostapd_nai_realm_data *realm;
1433	size_t i, j, len;
1434	int *offsets;
1435	char *pos, *end, *rpos;
1436
1437	offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS,
1438			    sizeof(int));
1439	if (offsets == NULL)
1440		return -1;
1441
1442	for (i = 0; i < bss->nai_realm_count; i++) {
1443		realm = &bss->nai_realm_data[i];
1444		for (j = 0; j < MAX_NAI_REALMS; j++) {
1445			offsets[i * MAX_NAI_REALMS + j] =
1446				realm->realm[j] ?
1447				realm->realm[j] - realm->realm_buf : -1;
1448		}
1449	}
1450
1451	realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1,
1452				 sizeof(struct hostapd_nai_realm_data));
1453	if (realm == NULL) {
1454		os_free(offsets);
1455		return -1;
1456	}
1457	bss->nai_realm_data = realm;
1458
1459	/* patch the pointers after realloc */
1460	for (i = 0; i < bss->nai_realm_count; i++) {
1461		realm = &bss->nai_realm_data[i];
1462		for (j = 0; j < MAX_NAI_REALMS; j++) {
1463			int offs = offsets[i * MAX_NAI_REALMS + j];
1464			if (offs >= 0)
1465				realm->realm[j] = realm->realm_buf + offs;
1466			else
1467				realm->realm[j] = NULL;
1468		}
1469	}
1470	os_free(offsets);
1471
1472	realm = &bss->nai_realm_data[bss->nai_realm_count];
1473	os_memset(realm, 0, sizeof(*realm));
1474
1475	pos = buf;
1476	realm->encoding = atoi(pos);
1477	pos = os_strchr(pos, ',');
1478	if (pos == NULL)
1479		goto fail;
1480	pos++;
1481
1482	end = os_strchr(pos, ',');
1483	if (end) {
1484		len = end - pos;
1485		*end = '\0';
1486	} else {
1487		len = os_strlen(pos);
1488	}
1489
1490	if (len > MAX_NAI_REALMLEN) {
1491		wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d "
1492			   "characters)", (int) len, MAX_NAI_REALMLEN);
1493		goto fail;
1494	}
1495	os_memcpy(realm->realm_buf, pos, len);
1496
1497	if (end)
1498		pos = end + 1;
1499	else
1500		pos = NULL;
1501
1502	while (pos && *pos) {
1503		struct hostapd_nai_realm_eap *eap;
1504
1505		if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) {
1506			wpa_printf(MSG_ERROR, "Too many EAP methods");
1507			goto fail;
1508		}
1509
1510		eap = &realm->eap_method[realm->eap_method_count];
1511		realm->eap_method_count++;
1512
1513		end = os_strchr(pos, ',');
1514		if (end == NULL)
1515			end = pos + os_strlen(pos);
1516
1517		eap->eap_method = atoi(pos);
1518		for (;;) {
1519			pos = os_strchr(pos, '[');
1520			if (pos == NULL || pos > end)
1521				break;
1522			pos++;
1523			if (eap->num_auths >= MAX_NAI_AUTH_TYPES) {
1524				wpa_printf(MSG_ERROR, "Too many auth params");
1525				goto fail;
1526			}
1527			eap->auth_id[eap->num_auths] = atoi(pos);
1528			pos = os_strchr(pos, ':');
1529			if (pos == NULL || pos > end)
1530				goto fail;
1531			pos++;
1532			eap->auth_val[eap->num_auths] = atoi(pos);
1533			pos = os_strchr(pos, ']');
1534			if (pos == NULL || pos > end)
1535				goto fail;
1536			pos++;
1537			eap->num_auths++;
1538		}
1539
1540		if (*end != ',')
1541			break;
1542
1543		pos = end + 1;
1544	}
1545
1546	/* Split realm list into null terminated realms */
1547	rpos = realm->realm_buf;
1548	i = 0;
1549	while (*rpos) {
1550		if (i >= MAX_NAI_REALMS) {
1551			wpa_printf(MSG_ERROR, "Too many realms");
1552			goto fail;
1553		}
1554		realm->realm[i++] = rpos;
1555		rpos = os_strchr(rpos, ';');
1556		if (rpos == NULL)
1557			break;
1558		*rpos++ = '\0';
1559	}
1560
1561	bss->nai_realm_count++;
1562
1563	return 0;
1564
1565fail:
1566	wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf);
1567	return -1;
1568}
1569
1570#endif /* CONFIG_INTERWORKING */
1571
1572
1573#ifdef CONFIG_HS20
1574static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
1575				 int line)
1576{
1577	u8 *conn_cap;
1578	char *pos;
1579
1580	if (bss->hs20_connection_capability_len >= 0xfff0)
1581		return -1;
1582
1583	conn_cap = os_realloc(bss->hs20_connection_capability,
1584			      bss->hs20_connection_capability_len + 4);
1585	if (conn_cap == NULL)
1586		return -1;
1587
1588	bss->hs20_connection_capability = conn_cap;
1589	conn_cap += bss->hs20_connection_capability_len;
1590	pos = buf;
1591	conn_cap[0] = atoi(pos);
1592	pos = os_strchr(pos, ':');
1593	if (pos == NULL)
1594		return -1;
1595	pos++;
1596	WPA_PUT_LE16(conn_cap + 1, atoi(pos));
1597	pos = os_strchr(pos, ':');
1598	if (pos == NULL)
1599		return -1;
1600	pos++;
1601	conn_cap[3] = atoi(pos);
1602	bss->hs20_connection_capability_len += 4;
1603
1604	return 0;
1605}
1606
1607
1608static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf,
1609				  int line)
1610{
1611	u8 *wan_metrics;
1612	char *pos;
1613
1614	/* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */
1615
1616	wan_metrics = os_zalloc(13);
1617	if (wan_metrics == NULL)
1618		return -1;
1619
1620	pos = buf;
1621	/* WAN Info */
1622	if (hexstr2bin(pos, wan_metrics, 1) < 0)
1623		goto fail;
1624	pos += 2;
1625	if (*pos != ':')
1626		goto fail;
1627	pos++;
1628
1629	/* Downlink Speed */
1630	WPA_PUT_LE32(wan_metrics + 1, atoi(pos));
1631	pos = os_strchr(pos, ':');
1632	if (pos == NULL)
1633		goto fail;
1634	pos++;
1635
1636	/* Uplink Speed */
1637	WPA_PUT_LE32(wan_metrics + 5, atoi(pos));
1638	pos = os_strchr(pos, ':');
1639	if (pos == NULL)
1640		goto fail;
1641	pos++;
1642
1643	/* Downlink Load */
1644	wan_metrics[9] = atoi(pos);
1645	pos = os_strchr(pos, ':');
1646	if (pos == NULL)
1647		goto fail;
1648	pos++;
1649
1650	/* Uplink Load */
1651	wan_metrics[10] = atoi(pos);
1652	pos = os_strchr(pos, ':');
1653	if (pos == NULL)
1654		goto fail;
1655	pos++;
1656
1657	/* LMD */
1658	WPA_PUT_LE16(wan_metrics + 11, atoi(pos));
1659
1660	os_free(bss->hs20_wan_metrics);
1661	bss->hs20_wan_metrics = wan_metrics;
1662
1663	return 0;
1664
1665fail:
1666	wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'",
1667		   line, pos);
1668	os_free(wan_metrics);
1669	return -1;
1670}
1671
1672
1673static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
1674					 char *pos, int line)
1675{
1676	if (parse_lang_string(&bss->hs20_oper_friendly_name,
1677			      &bss->hs20_oper_friendly_name_count, pos)) {
1678		wpa_printf(MSG_ERROR, "Line %d: Invalid "
1679			   "hs20_oper_friendly_name '%s'", line, pos);
1680		return -1;
1681	}
1682	return 0;
1683}
1684#endif /* CONFIG_HS20 */
1685
1686
1687#ifdef CONFIG_WPS_NFC
1688static struct wpabuf * hostapd_parse_bin(const char *buf)
1689{
1690	size_t len;
1691	struct wpabuf *ret;
1692
1693	len = os_strlen(buf);
1694	if (len & 0x01)
1695		return NULL;
1696	len /= 2;
1697
1698	ret = wpabuf_alloc(len);
1699	if (ret == NULL)
1700		return NULL;
1701
1702	if (hexstr2bin(buf, wpabuf_put(ret, len), len)) {
1703		wpabuf_free(ret);
1704		return NULL;
1705	}
1706
1707	return ret;
1708}
1709#endif /* CONFIG_WPS_NFC */
1710
1711
1712static int hostapd_config_fill(struct hostapd_config *conf,
1713			       struct hostapd_bss_config *bss,
1714			       char *buf, char *pos, int line)
1715{
1716	int errors = 0;
1717
1718	{
1719		if (os_strcmp(buf, "interface") == 0) {
1720			os_strlcpy(conf->bss[0].iface, pos,
1721				   sizeof(conf->bss[0].iface));
1722		} else if (os_strcmp(buf, "bridge") == 0) {
1723			os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
1724		} else if (os_strcmp(buf, "wds_bridge") == 0) {
1725			os_strlcpy(bss->wds_bridge, pos,
1726				   sizeof(bss->wds_bridge));
1727		} else if (os_strcmp(buf, "driver") == 0) {
1728			int j;
1729			/* clear to get error below if setting is invalid */
1730			conf->driver = NULL;
1731			for (j = 0; wpa_drivers[j]; j++) {
1732				if (os_strcmp(pos, wpa_drivers[j]->name) == 0)
1733				{
1734					conf->driver = wpa_drivers[j];
1735					break;
1736				}
1737			}
1738			if (conf->driver == NULL) {
1739				wpa_printf(MSG_ERROR, "Line %d: invalid/"
1740					   "unknown driver '%s'", line, pos);
1741				errors++;
1742			}
1743		} else if (os_strcmp(buf, "debug") == 0) {
1744			wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' "
1745				   "configuration variable is not used "
1746				   "anymore", line);
1747		} else if (os_strcmp(buf, "logger_syslog_level") == 0) {
1748			bss->logger_syslog_level = atoi(pos);
1749		} else if (os_strcmp(buf, "logger_stdout_level") == 0) {
1750			bss->logger_stdout_level = atoi(pos);
1751		} else if (os_strcmp(buf, "logger_syslog") == 0) {
1752			bss->logger_syslog = atoi(pos);
1753		} else if (os_strcmp(buf, "logger_stdout") == 0) {
1754			bss->logger_stdout = atoi(pos);
1755		} else if (os_strcmp(buf, "dump_file") == 0) {
1756			bss->dump_log_name = os_strdup(pos);
1757		} else if (os_strcmp(buf, "ssid") == 0) {
1758			bss->ssid.ssid_len = os_strlen(pos);
1759			if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
1760			    bss->ssid.ssid_len < 1) {
1761				wpa_printf(MSG_ERROR, "Line %d: invalid SSID "
1762					   "'%s'", line, pos);
1763				errors++;
1764			} else {
1765				os_memcpy(bss->ssid.ssid, pos,
1766					  bss->ssid.ssid_len);
1767				bss->ssid.ssid_set = 1;
1768			}
1769		} else if (os_strcmp(buf, "ssid2") == 0) {
1770			size_t slen;
1771			char *str = wpa_config_parse_string(pos, &slen);
1772			if (str == NULL || slen < 1 ||
1773				   slen > HOSTAPD_MAX_SSID_LEN) {
1774				wpa_printf(MSG_ERROR, "Line %d: invalid SSID "
1775					   "'%s'", line, pos);
1776				errors++;
1777			} else {
1778				os_memcpy(bss->ssid.ssid, str, slen);
1779				bss->ssid.ssid_len = slen;
1780				bss->ssid.ssid_set = 1;
1781			}
1782			os_free(str);
1783		} else if (os_strcmp(buf, "utf8_ssid") == 0) {
1784			bss->ssid.utf8_ssid = atoi(pos) > 0;
1785		} else if (os_strcmp(buf, "macaddr_acl") == 0) {
1786			bss->macaddr_acl = atoi(pos);
1787			if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
1788			    bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
1789			    bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1790				wpa_printf(MSG_ERROR, "Line %d: unknown "
1791					   "macaddr_acl %d",
1792					   line, bss->macaddr_acl);
1793			}
1794		} else if (os_strcmp(buf, "accept_mac_file") == 0) {
1795			if (hostapd_config_read_maclist(pos, &bss->accept_mac,
1796							&bss->num_accept_mac))
1797			{
1798				wpa_printf(MSG_ERROR, "Line %d: Failed to "
1799					   "read accept_mac_file '%s'",
1800					   line, pos);
1801				errors++;
1802			}
1803		} else if (os_strcmp(buf, "deny_mac_file") == 0) {
1804			if (hostapd_config_read_maclist(pos, &bss->deny_mac,
1805							&bss->num_deny_mac)) {
1806				wpa_printf(MSG_ERROR, "Line %d: Failed to "
1807					   "read deny_mac_file '%s'",
1808					   line, pos);
1809				errors++;
1810			}
1811		} else if (os_strcmp(buf, "wds_sta") == 0) {
1812			bss->wds_sta = atoi(pos);
1813		} else if (os_strcmp(buf, "ap_isolate") == 0) {
1814			bss->isolate = atoi(pos);
1815		} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
1816			bss->ap_max_inactivity = atoi(pos);
1817		} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
1818			bss->skip_inactivity_poll = atoi(pos);
1819		} else if (os_strcmp(buf, "country_code") == 0) {
1820			os_memcpy(conf->country, pos, 2);
1821			/* FIX: make this configurable */
1822			conf->country[2] = ' ';
1823		} else if (os_strcmp(buf, "ieee80211d") == 0) {
1824			conf->ieee80211d = atoi(pos);
1825		} else if (os_strcmp(buf, "ieee8021x") == 0) {
1826			bss->ieee802_1x = atoi(pos);
1827		} else if (os_strcmp(buf, "eapol_version") == 0) {
1828			bss->eapol_version = atoi(pos);
1829			if (bss->eapol_version < 1 ||
1830			    bss->eapol_version > 2) {
1831				wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL "
1832					   "version (%d): '%s'.",
1833					   line, bss->eapol_version, pos);
1834				errors++;
1835			} else
1836				wpa_printf(MSG_DEBUG, "eapol_version=%d",
1837					   bss->eapol_version);
1838#ifdef EAP_SERVER
1839		} else if (os_strcmp(buf, "eap_authenticator") == 0) {
1840			bss->eap_server = atoi(pos);
1841			wpa_printf(MSG_ERROR, "Line %d: obsolete "
1842				   "eap_authenticator used; this has been "
1843				   "renamed to eap_server", line);
1844		} else if (os_strcmp(buf, "eap_server") == 0) {
1845			bss->eap_server = atoi(pos);
1846		} else if (os_strcmp(buf, "eap_user_file") == 0) {
1847			if (hostapd_config_read_eap_user(pos, bss))
1848				errors++;
1849		} else if (os_strcmp(buf, "ca_cert") == 0) {
1850			os_free(bss->ca_cert);
1851			bss->ca_cert = os_strdup(pos);
1852		} else if (os_strcmp(buf, "server_cert") == 0) {
1853			os_free(bss->server_cert);
1854			bss->server_cert = os_strdup(pos);
1855		} else if (os_strcmp(buf, "private_key") == 0) {
1856			os_free(bss->private_key);
1857			bss->private_key = os_strdup(pos);
1858		} else if (os_strcmp(buf, "private_key_passwd") == 0) {
1859			os_free(bss->private_key_passwd);
1860			bss->private_key_passwd = os_strdup(pos);
1861		} else if (os_strcmp(buf, "check_crl") == 0) {
1862			bss->check_crl = atoi(pos);
1863		} else if (os_strcmp(buf, "dh_file") == 0) {
1864			os_free(bss->dh_file);
1865			bss->dh_file = os_strdup(pos);
1866		} else if (os_strcmp(buf, "fragment_size") == 0) {
1867			bss->fragment_size = atoi(pos);
1868#ifdef EAP_SERVER_FAST
1869		} else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
1870			os_free(bss->pac_opaque_encr_key);
1871			bss->pac_opaque_encr_key = os_malloc(16);
1872			if (bss->pac_opaque_encr_key == NULL) {
1873				wpa_printf(MSG_ERROR, "Line %d: No memory for "
1874					   "pac_opaque_encr_key", line);
1875				errors++;
1876			} else if (hexstr2bin(pos, bss->pac_opaque_encr_key,
1877					      16)) {
1878				wpa_printf(MSG_ERROR, "Line %d: Invalid "
1879					   "pac_opaque_encr_key", line);
1880				errors++;
1881			}
1882		} else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
1883			size_t idlen = os_strlen(pos);
1884			if (idlen & 1) {
1885				wpa_printf(MSG_ERROR, "Line %d: Invalid "
1886					   "eap_fast_a_id", line);
1887				errors++;
1888			} else {
1889				os_free(bss->eap_fast_a_id);
1890				bss->eap_fast_a_id = os_malloc(idlen / 2);
1891				if (bss->eap_fast_a_id == NULL ||
1892				    hexstr2bin(pos, bss->eap_fast_a_id,
1893					       idlen / 2)) {
1894					wpa_printf(MSG_ERROR, "Line %d: "
1895						   "Failed to parse "
1896						   "eap_fast_a_id", line);
1897					errors++;
1898				} else
1899					bss->eap_fast_a_id_len = idlen / 2;
1900			}
1901		} else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
1902			os_free(bss->eap_fast_a_id_info);
1903			bss->eap_fast_a_id_info = os_strdup(pos);
1904		} else if (os_strcmp(buf, "eap_fast_prov") == 0) {
1905			bss->eap_fast_prov = atoi(pos);
1906		} else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
1907			bss->pac_key_lifetime = atoi(pos);
1908		} else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
1909			bss->pac_key_refresh_time = atoi(pos);
1910#endif /* EAP_SERVER_FAST */
1911#ifdef EAP_SERVER_SIM
1912		} else if (os_strcmp(buf, "eap_sim_db") == 0) {
1913			os_free(bss->eap_sim_db);
1914			bss->eap_sim_db = os_strdup(pos);
1915		} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
1916			bss->eap_sim_aka_result_ind = atoi(pos);
1917#endif /* EAP_SERVER_SIM */
1918#ifdef EAP_SERVER_TNC
1919		} else if (os_strcmp(buf, "tnc") == 0) {
1920			bss->tnc = atoi(pos);
1921#endif /* EAP_SERVER_TNC */
1922#ifdef EAP_SERVER_PWD
1923		} else if (os_strcmp(buf, "pwd_group") == 0) {
1924			bss->pwd_group = atoi(pos);
1925#endif /* EAP_SERVER_PWD */
1926#endif /* EAP_SERVER */
1927		} else if (os_strcmp(buf, "eap_message") == 0) {
1928			char *term;
1929			bss->eap_req_id_text = os_strdup(pos);
1930			if (bss->eap_req_id_text == NULL) {
1931				wpa_printf(MSG_ERROR, "Line %d: Failed to "
1932					   "allocate memory for "
1933					   "eap_req_id_text", line);
1934				errors++;
1935				return errors;
1936			}
1937			bss->eap_req_id_text_len =
1938				os_strlen(bss->eap_req_id_text);
1939			term = os_strstr(bss->eap_req_id_text, "\\0");
1940			if (term) {
1941				*term++ = '\0';
1942				os_memmove(term, term + 1,
1943					   bss->eap_req_id_text_len -
1944					   (term - bss->eap_req_id_text) - 1);
1945				bss->eap_req_id_text_len--;
1946			}
1947		} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
1948			bss->default_wep_key_len = atoi(pos);
1949			if (bss->default_wep_key_len > 13) {
1950				wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
1951					   "key len %lu (= %lu bits)", line,
1952					   (unsigned long)
1953					   bss->default_wep_key_len,
1954					   (unsigned long)
1955					   bss->default_wep_key_len * 8);
1956				errors++;
1957			}
1958		} else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
1959			bss->individual_wep_key_len = atoi(pos);
1960			if (bss->individual_wep_key_len < 0 ||
1961			    bss->individual_wep_key_len > 13) {
1962				wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
1963					   "key len %d (= %d bits)", line,
1964					   bss->individual_wep_key_len,
1965					   bss->individual_wep_key_len * 8);
1966				errors++;
1967			}
1968		} else if (os_strcmp(buf, "wep_rekey_period") == 0) {
1969			bss->wep_rekeying_period = atoi(pos);
1970			if (bss->wep_rekeying_period < 0) {
1971				wpa_printf(MSG_ERROR, "Line %d: invalid "
1972					   "period %d",
1973					   line, bss->wep_rekeying_period);
1974				errors++;
1975			}
1976		} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
1977			bss->eap_reauth_period = atoi(pos);
1978			if (bss->eap_reauth_period < 0) {
1979				wpa_printf(MSG_ERROR, "Line %d: invalid "
1980					   "period %d",
1981					   line, bss->eap_reauth_period);
1982				errors++;
1983			}
1984		} else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
1985			bss->eapol_key_index_workaround = atoi(pos);
1986#ifdef CONFIG_IAPP
1987		} else if (os_strcmp(buf, "iapp_interface") == 0) {
1988			bss->ieee802_11f = 1;
1989			os_strlcpy(bss->iapp_iface, pos,
1990				   sizeof(bss->iapp_iface));
1991#endif /* CONFIG_IAPP */
1992		} else if (os_strcmp(buf, "own_ip_addr") == 0) {
1993			if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
1994				wpa_printf(MSG_ERROR, "Line %d: invalid IP "
1995					   "address '%s'", line, pos);
1996				errors++;
1997			}
1998		} else if (os_strcmp(buf, "nas_identifier") == 0) {
1999			bss->nas_identifier = os_strdup(pos);
2000#ifndef CONFIG_NO_RADIUS
2001		} else if (os_strcmp(buf, "auth_server_addr") == 0) {
2002			if (hostapd_config_read_radius_addr(
2003				    &bss->radius->auth_servers,
2004				    &bss->radius->num_auth_servers, pos, 1812,
2005				    &bss->radius->auth_server)) {
2006				wpa_printf(MSG_ERROR, "Line %d: invalid IP "
2007					   "address '%s'", line, pos);
2008				errors++;
2009			}
2010		} else if (bss->radius->auth_server &&
2011			   os_strcmp(buf, "auth_server_port") == 0) {
2012			bss->radius->auth_server->port = atoi(pos);
2013		} else if (bss->radius->auth_server &&
2014			   os_strcmp(buf, "auth_server_shared_secret") == 0) {
2015			int len = os_strlen(pos);
2016			if (len == 0) {
2017				/* RFC 2865, Ch. 3 */
2018				wpa_printf(MSG_ERROR, "Line %d: empty shared "
2019					   "secret is not allowed.", line);
2020				errors++;
2021			}
2022			bss->radius->auth_server->shared_secret =
2023				(u8 *) os_strdup(pos);
2024			bss->radius->auth_server->shared_secret_len = len;
2025		} else if (os_strcmp(buf, "acct_server_addr") == 0) {
2026			if (hostapd_config_read_radius_addr(
2027				    &bss->radius->acct_servers,
2028				    &bss->radius->num_acct_servers, pos, 1813,
2029				    &bss->radius->acct_server)) {
2030				wpa_printf(MSG_ERROR, "Line %d: invalid IP "
2031					   "address '%s'", line, pos);
2032				errors++;
2033			}
2034		} else if (bss->radius->acct_server &&
2035			   os_strcmp(buf, "acct_server_port") == 0) {
2036			bss->radius->acct_server->port = atoi(pos);
2037		} else if (bss->radius->acct_server &&
2038			   os_strcmp(buf, "acct_server_shared_secret") == 0) {
2039			int len = os_strlen(pos);
2040			if (len == 0) {
2041				/* RFC 2865, Ch. 3 */
2042				wpa_printf(MSG_ERROR, "Line %d: empty shared "
2043					   "secret is not allowed.", line);
2044				errors++;
2045			}
2046			bss->radius->acct_server->shared_secret =
2047				(u8 *) os_strdup(pos);
2048			bss->radius->acct_server->shared_secret_len = len;
2049		} else if (os_strcmp(buf, "radius_retry_primary_interval") ==
2050			   0) {
2051			bss->radius->retry_primary_interval = atoi(pos);
2052		} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0)
2053		{
2054			bss->acct_interim_interval = atoi(pos);
2055		} else if (os_strcmp(buf, "radius_request_cui") == 0) {
2056			bss->radius_request_cui = atoi(pos);
2057		} else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
2058			struct hostapd_radius_attr *attr, *a;
2059			attr = hostapd_parse_radius_attr(pos);
2060			if (attr == NULL) {
2061				wpa_printf(MSG_ERROR, "Line %d: invalid "
2062					   "radius_auth_req_attr", line);
2063				errors++;
2064			} else if (bss->radius_auth_req_attr == NULL) {
2065				bss->radius_auth_req_attr = attr;
2066			} else {
2067				a = bss->radius_auth_req_attr;
2068				while (a->next)
2069					a = a->next;
2070				a->next = attr;
2071			}
2072		} else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
2073			struct hostapd_radius_attr *attr, *a;
2074			attr = hostapd_parse_radius_attr(pos);
2075			if (attr == NULL) {
2076				wpa_printf(MSG_ERROR, "Line %d: invalid "
2077					   "radius_acct_req_attr", line);
2078				errors++;
2079			} else if (bss->radius_acct_req_attr == NULL) {
2080				bss->radius_acct_req_attr = attr;
2081			} else {
2082				a = bss->radius_acct_req_attr;
2083				while (a->next)
2084					a = a->next;
2085				a->next = attr;
2086			}
2087		} else if (os_strcmp(buf, "radius_das_port") == 0) {
2088			bss->radius_das_port = atoi(pos);
2089		} else if (os_strcmp(buf, "radius_das_client") == 0) {
2090			if (hostapd_parse_das_client(bss, pos) < 0) {
2091				wpa_printf(MSG_ERROR, "Line %d: invalid "
2092					   "DAS client", line);
2093				errors++;
2094			}
2095		} else if (os_strcmp(buf, "radius_das_time_window") == 0) {
2096			bss->radius_das_time_window = atoi(pos);
2097		} else if (os_strcmp(buf, "radius_das_require_event_timestamp")
2098			   == 0) {
2099			bss->radius_das_require_event_timestamp = atoi(pos);
2100#endif /* CONFIG_NO_RADIUS */
2101		} else if (os_strcmp(buf, "auth_algs") == 0) {
2102			bss->auth_algs = atoi(pos);
2103			if (bss->auth_algs == 0) {
2104				wpa_printf(MSG_ERROR, "Line %d: no "
2105					   "authentication algorithms allowed",
2106					   line);
2107				errors++;
2108			}
2109		} else if (os_strcmp(buf, "max_num_sta") == 0) {
2110			bss->max_num_sta = atoi(pos);
2111			if (bss->max_num_sta < 0 ||
2112			    bss->max_num_sta > MAX_STA_COUNT) {
2113				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2114					   "max_num_sta=%d; allowed range "
2115					   "0..%d", line, bss->max_num_sta,
2116					   MAX_STA_COUNT);
2117				errors++;
2118			}
2119		} else if (os_strcmp(buf, "wpa") == 0) {
2120			bss->wpa = atoi(pos);
2121		} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
2122			bss->wpa_group_rekey = atoi(pos);
2123		} else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
2124			bss->wpa_strict_rekey = atoi(pos);
2125		} else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
2126			bss->wpa_gmk_rekey = atoi(pos);
2127		} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
2128			bss->wpa_ptk_rekey = atoi(pos);
2129		} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
2130			int len = os_strlen(pos);
2131			if (len < 8 || len > 63) {
2132				wpa_printf(MSG_ERROR, "Line %d: invalid WPA "
2133					   "passphrase length %d (expected "
2134					   "8..63)", line, len);
2135				errors++;
2136			} else {
2137				os_free(bss->ssid.wpa_passphrase);
2138				bss->ssid.wpa_passphrase = os_strdup(pos);
2139				os_free(bss->ssid.wpa_psk);
2140				bss->ssid.wpa_psk = NULL;
2141			}
2142		} else if (os_strcmp(buf, "wpa_psk") == 0) {
2143			os_free(bss->ssid.wpa_psk);
2144			bss->ssid.wpa_psk =
2145				os_zalloc(sizeof(struct hostapd_wpa_psk));
2146			if (bss->ssid.wpa_psk == NULL)
2147				errors++;
2148			else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk,
2149					    PMK_LEN) ||
2150				 pos[PMK_LEN * 2] != '\0') {
2151				wpa_printf(MSG_ERROR, "Line %d: Invalid PSK "
2152					   "'%s'.", line, pos);
2153				errors++;
2154			} else {
2155				bss->ssid.wpa_psk->group = 1;
2156				os_free(bss->ssid.wpa_passphrase);
2157				bss->ssid.wpa_passphrase = NULL;
2158			}
2159		} else if (os_strcmp(buf, "wpa_psk_file") == 0) {
2160			os_free(bss->ssid.wpa_psk_file);
2161			bss->ssid.wpa_psk_file = os_strdup(pos);
2162			if (!bss->ssid.wpa_psk_file) {
2163				wpa_printf(MSG_ERROR, "Line %d: allocation "
2164					   "failed", line);
2165				errors++;
2166			}
2167		} else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
2168			bss->wpa_key_mgmt =
2169				hostapd_config_parse_key_mgmt(line, pos);
2170			if (bss->wpa_key_mgmt == -1)
2171				errors++;
2172		} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
2173			bss->wpa_psk_radius = atoi(pos);
2174			if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
2175			    bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
2176			    bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
2177				wpa_printf(MSG_ERROR, "Line %d: unknown "
2178					   "wpa_psk_radius %d",
2179					   line, bss->wpa_psk_radius);
2180				errors++;
2181			}
2182		} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
2183			bss->wpa_pairwise =
2184				hostapd_config_parse_cipher(line, pos);
2185			if (bss->wpa_pairwise == -1 ||
2186			    bss->wpa_pairwise == 0)
2187				errors++;
2188			else if (bss->wpa_pairwise &
2189				 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
2190				  WPA_CIPHER_WEP104)) {
2191				wpa_printf(MSG_ERROR, "Line %d: unsupported "
2192					   "pairwise cipher suite '%s'",
2193					   bss->wpa_pairwise, pos);
2194				errors++;
2195			}
2196		} else if (os_strcmp(buf, "rsn_pairwise") == 0) {
2197			bss->rsn_pairwise =
2198				hostapd_config_parse_cipher(line, pos);
2199			if (bss->rsn_pairwise == -1 ||
2200			    bss->rsn_pairwise == 0)
2201				errors++;
2202			else if (bss->rsn_pairwise &
2203				 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
2204				  WPA_CIPHER_WEP104)) {
2205				wpa_printf(MSG_ERROR, "Line %d: unsupported "
2206					   "pairwise cipher suite '%s'",
2207					   bss->rsn_pairwise, pos);
2208				errors++;
2209			}
2210#ifdef CONFIG_RSN_PREAUTH
2211		} else if (os_strcmp(buf, "rsn_preauth") == 0) {
2212			bss->rsn_preauth = atoi(pos);
2213		} else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
2214			bss->rsn_preauth_interfaces = os_strdup(pos);
2215#endif /* CONFIG_RSN_PREAUTH */
2216#ifdef CONFIG_PEERKEY
2217		} else if (os_strcmp(buf, "peerkey") == 0) {
2218			bss->peerkey = atoi(pos);
2219#endif /* CONFIG_PEERKEY */
2220#ifdef CONFIG_IEEE80211R
2221		} else if (os_strcmp(buf, "mobility_domain") == 0) {
2222			if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
2223			    hexstr2bin(pos, bss->mobility_domain,
2224				       MOBILITY_DOMAIN_ID_LEN) != 0) {
2225				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2226					   "mobility_domain '%s'", line, pos);
2227				errors++;
2228				return errors;
2229			}
2230		} else if (os_strcmp(buf, "r1_key_holder") == 0) {
2231			if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
2232			    hexstr2bin(pos, bss->r1_key_holder,
2233				       FT_R1KH_ID_LEN) != 0) {
2234				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2235					   "r1_key_holder '%s'", line, pos);
2236				errors++;
2237				return errors;
2238			}
2239		} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
2240			bss->r0_key_lifetime = atoi(pos);
2241		} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
2242			bss->reassociation_deadline = atoi(pos);
2243		} else if (os_strcmp(buf, "r0kh") == 0) {
2244			if (add_r0kh(bss, pos) < 0) {
2245				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2246					   "r0kh '%s'", line, pos);
2247				errors++;
2248				return errors;
2249			}
2250		} else if (os_strcmp(buf, "r1kh") == 0) {
2251			if (add_r1kh(bss, pos) < 0) {
2252				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2253					   "r1kh '%s'", line, pos);
2254				errors++;
2255				return errors;
2256			}
2257		} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
2258			bss->pmk_r1_push = atoi(pos);
2259		} else if (os_strcmp(buf, "ft_over_ds") == 0) {
2260			bss->ft_over_ds = atoi(pos);
2261#endif /* CONFIG_IEEE80211R */
2262#ifndef CONFIG_NO_CTRL_IFACE
2263		} else if (os_strcmp(buf, "ctrl_interface") == 0) {
2264			os_free(bss->ctrl_interface);
2265			bss->ctrl_interface = os_strdup(pos);
2266		} else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
2267#ifndef CONFIG_NATIVE_WINDOWS
2268			struct group *grp;
2269			char *endp;
2270			const char *group = pos;
2271
2272			grp = getgrnam(group);
2273			if (grp) {
2274				bss->ctrl_interface_gid = grp->gr_gid;
2275				bss->ctrl_interface_gid_set = 1;
2276				wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
2277					   " (from group name '%s')",
2278					   bss->ctrl_interface_gid, group);
2279				return errors;
2280			}
2281
2282			/* Group name not found - try to parse this as gid */
2283			bss->ctrl_interface_gid = strtol(group, &endp, 10);
2284			if (*group == '\0' || *endp != '\0') {
2285				wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
2286					   "'%s'", line, group);
2287				errors++;
2288				return errors;
2289			}
2290			bss->ctrl_interface_gid_set = 1;
2291			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
2292				   bss->ctrl_interface_gid);
2293#endif /* CONFIG_NATIVE_WINDOWS */
2294#endif /* CONFIG_NO_CTRL_IFACE */
2295#ifdef RADIUS_SERVER
2296		} else if (os_strcmp(buf, "radius_server_clients") == 0) {
2297			os_free(bss->radius_server_clients);
2298			bss->radius_server_clients = os_strdup(pos);
2299		} else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
2300			bss->radius_server_auth_port = atoi(pos);
2301		} else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
2302			bss->radius_server_ipv6 = atoi(pos);
2303#endif /* RADIUS_SERVER */
2304		} else if (os_strcmp(buf, "test_socket") == 0) {
2305			os_free(bss->test_socket);
2306			bss->test_socket = os_strdup(pos);
2307		} else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
2308			bss->use_pae_group_addr = atoi(pos);
2309		} else if (os_strcmp(buf, "hw_mode") == 0) {
2310			if (os_strcmp(pos, "a") == 0)
2311				conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
2312			else if (os_strcmp(pos, "b") == 0)
2313				conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
2314			else if (os_strcmp(pos, "g") == 0)
2315				conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
2316			else if (os_strcmp(pos, "ad") == 0)
2317				conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
2318			else {
2319				wpa_printf(MSG_ERROR, "Line %d: unknown "
2320					   "hw_mode '%s'", line, pos);
2321				errors++;
2322			}
2323		} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
2324			if (os_strcmp(pos, "a") == 0)
2325				bss->wps_rf_bands = WPS_RF_50GHZ;
2326			else if (os_strcmp(pos, "g") == 0 ||
2327				 os_strcmp(pos, "b") == 0)
2328				bss->wps_rf_bands = WPS_RF_24GHZ;
2329			else if (os_strcmp(pos, "ag") == 0 ||
2330				 os_strcmp(pos, "ga") == 0)
2331				bss->wps_rf_bands =
2332					WPS_RF_24GHZ | WPS_RF_50GHZ;
2333			else {
2334				wpa_printf(MSG_ERROR, "Line %d: unknown "
2335					   "wps_rf_band '%s'", line, pos);
2336				errors++;
2337			}
2338		} else if (os_strcmp(buf, "channel") == 0) {
2339			conf->channel = atoi(pos);
2340		} else if (os_strcmp(buf, "beacon_int") == 0) {
2341			int val = atoi(pos);
2342			/* MIB defines range as 1..65535, but very small values
2343			 * cause problems with the current implementation.
2344			 * Since it is unlikely that this small numbers are
2345			 * useful in real life scenarios, do not allow beacon
2346			 * period to be set below 15 TU. */
2347			if (val < 15 || val > 65535) {
2348				wpa_printf(MSG_ERROR, "Line %d: invalid "
2349					   "beacon_int %d (expected "
2350					   "15..65535)", line, val);
2351				errors++;
2352			} else
2353				conf->beacon_int = val;
2354		} else if (os_strcmp(buf, "dtim_period") == 0) {
2355			bss->dtim_period = atoi(pos);
2356			if (bss->dtim_period < 1 || bss->dtim_period > 255) {
2357				wpa_printf(MSG_ERROR, "Line %d: invalid "
2358					   "dtim_period %d",
2359					   line, bss->dtim_period);
2360				errors++;
2361			}
2362		} else if (os_strcmp(buf, "rts_threshold") == 0) {
2363			conf->rts_threshold = atoi(pos);
2364			if (conf->rts_threshold < 0 ||
2365			    conf->rts_threshold > 2347) {
2366				wpa_printf(MSG_ERROR, "Line %d: invalid "
2367					   "rts_threshold %d",
2368					   line, conf->rts_threshold);
2369				errors++;
2370			}
2371		} else if (os_strcmp(buf, "fragm_threshold") == 0) {
2372			conf->fragm_threshold = atoi(pos);
2373			if (conf->fragm_threshold < 256 ||
2374			    conf->fragm_threshold > 2346) {
2375				wpa_printf(MSG_ERROR, "Line %d: invalid "
2376					   "fragm_threshold %d",
2377					   line, conf->fragm_threshold);
2378				errors++;
2379			}
2380		} else if (os_strcmp(buf, "send_probe_response") == 0) {
2381			int val = atoi(pos);
2382			if (val != 0 && val != 1) {
2383				wpa_printf(MSG_ERROR, "Line %d: invalid "
2384					   "send_probe_response %d (expected "
2385					   "0 or 1)", line, val);
2386			} else
2387				conf->send_probe_response = val;
2388		} else if (os_strcmp(buf, "supported_rates") == 0) {
2389			if (hostapd_parse_rates(&conf->supported_rates, pos)) {
2390				wpa_printf(MSG_ERROR, "Line %d: invalid rate "
2391					   "list", line);
2392				errors++;
2393			}
2394		} else if (os_strcmp(buf, "basic_rates") == 0) {
2395			if (hostapd_parse_rates(&conf->basic_rates, pos)) {
2396				wpa_printf(MSG_ERROR, "Line %d: invalid rate "
2397					   "list", line);
2398				errors++;
2399			}
2400		} else if (os_strcmp(buf, "preamble") == 0) {
2401			if (atoi(pos))
2402				conf->preamble = SHORT_PREAMBLE;
2403			else
2404				conf->preamble = LONG_PREAMBLE;
2405		} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
2406			bss->ignore_broadcast_ssid = atoi(pos);
2407		} else if (os_strcmp(buf, "wep_default_key") == 0) {
2408			bss->ssid.wep.idx = atoi(pos);
2409			if (bss->ssid.wep.idx > 3) {
2410				wpa_printf(MSG_ERROR, "Invalid "
2411					   "wep_default_key index %d",
2412					   bss->ssid.wep.idx);
2413				errors++;
2414			}
2415		} else if (os_strcmp(buf, "wep_key0") == 0 ||
2416			   os_strcmp(buf, "wep_key1") == 0 ||
2417			   os_strcmp(buf, "wep_key2") == 0 ||
2418			   os_strcmp(buf, "wep_key3") == 0) {
2419			if (hostapd_config_read_wep(&bss->ssid.wep,
2420						    buf[7] - '0', pos)) {
2421				wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
2422					   "key '%s'", line, buf);
2423				errors++;
2424			}
2425#ifndef CONFIG_NO_VLAN
2426		} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
2427			bss->ssid.dynamic_vlan = atoi(pos);
2428		} else if (os_strcmp(buf, "vlan_file") == 0) {
2429			if (hostapd_config_read_vlan_file(bss, pos)) {
2430				wpa_printf(MSG_ERROR, "Line %d: failed to "
2431					   "read VLAN file '%s'", line, pos);
2432				errors++;
2433			}
2434		} else if (os_strcmp(buf, "vlan_naming") == 0) {
2435			bss->ssid.vlan_naming = atoi(pos);
2436			if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
2437			    bss->ssid.vlan_naming < 0) {
2438				wpa_printf(MSG_ERROR, "Line %d: invalid "
2439					   "naming scheme %d", line,
2440                                           bss->ssid.vlan_naming);
2441				errors++;
2442                        }
2443#ifdef CONFIG_FULL_DYNAMIC_VLAN
2444		} else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
2445			bss->ssid.vlan_tagged_interface = os_strdup(pos);
2446#endif /* CONFIG_FULL_DYNAMIC_VLAN */
2447#endif /* CONFIG_NO_VLAN */
2448		} else if (os_strcmp(buf, "ap_table_max_size") == 0) {
2449			conf->ap_table_max_size = atoi(pos);
2450		} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
2451			conf->ap_table_expiration_time = atoi(pos);
2452		} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
2453			if (hostapd_config_tx_queue(conf, buf, pos)) {
2454				wpa_printf(MSG_ERROR, "Line %d: invalid TX "
2455					   "queue item", line);
2456				errors++;
2457			}
2458		} else if (os_strcmp(buf, "wme_enabled") == 0 ||
2459			   os_strcmp(buf, "wmm_enabled") == 0) {
2460			bss->wmm_enabled = atoi(pos);
2461		} else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
2462			bss->wmm_uapsd = atoi(pos);
2463		} else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
2464			   os_strncmp(buf, "wmm_ac_", 7) == 0) {
2465			if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf,
2466						  pos)) {
2467				wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
2468					   "ac item", line);
2469				errors++;
2470			}
2471		} else if (os_strcmp(buf, "bss") == 0) {
2472			if (hostapd_config_bss(conf, pos)) {
2473				wpa_printf(MSG_ERROR, "Line %d: invalid bss "
2474					   "item", line);
2475				errors++;
2476			}
2477		} else if (os_strcmp(buf, "bssid") == 0) {
2478			if (hwaddr_aton(pos, bss->bssid)) {
2479				wpa_printf(MSG_ERROR, "Line %d: invalid bssid "
2480					   "item", line);
2481				errors++;
2482			}
2483#ifdef CONFIG_IEEE80211W
2484		} else if (os_strcmp(buf, "ieee80211w") == 0) {
2485			bss->ieee80211w = atoi(pos);
2486		} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
2487			bss->assoc_sa_query_max_timeout = atoi(pos);
2488			if (bss->assoc_sa_query_max_timeout == 0) {
2489				wpa_printf(MSG_ERROR, "Line %d: invalid "
2490					   "assoc_sa_query_max_timeout", line);
2491				errors++;
2492			}
2493		} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0)
2494		{
2495			bss->assoc_sa_query_retry_timeout = atoi(pos);
2496			if (bss->assoc_sa_query_retry_timeout == 0) {
2497				wpa_printf(MSG_ERROR, "Line %d: invalid "
2498					   "assoc_sa_query_retry_timeout",
2499					   line);
2500				errors++;
2501			}
2502#endif /* CONFIG_IEEE80211W */
2503#ifdef CONFIG_IEEE80211N
2504		} else if (os_strcmp(buf, "ieee80211n") == 0) {
2505			conf->ieee80211n = atoi(pos);
2506		} else if (os_strcmp(buf, "ht_capab") == 0) {
2507			if (hostapd_config_ht_capab(conf, pos) < 0) {
2508				wpa_printf(MSG_ERROR, "Line %d: invalid "
2509					   "ht_capab", line);
2510				errors++;
2511			}
2512		} else if (os_strcmp(buf, "require_ht") == 0) {
2513			conf->require_ht = atoi(pos);
2514#endif /* CONFIG_IEEE80211N */
2515#ifdef CONFIG_IEEE80211AC
2516		} else if (os_strcmp(buf, "ieee80211ac") == 0) {
2517			conf->ieee80211ac = atoi(pos);
2518		} else if (os_strcmp(buf, "vht_capab") == 0) {
2519			if (hostapd_config_vht_capab(conf, pos) < 0) {
2520				wpa_printf(MSG_ERROR, "Line %d: invalid "
2521					   "vht_capab", line);
2522				errors++;
2523			}
2524		} else if (os_strcmp(buf, "require_vht") == 0) {
2525			conf->require_vht = atoi(pos);
2526		} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
2527			conf->vht_oper_chwidth = atoi(pos);
2528		} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0)
2529		{
2530			conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
2531		} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0)
2532		{
2533			conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
2534#endif /* CONFIG_IEEE80211AC */
2535		} else if (os_strcmp(buf, "max_listen_interval") == 0) {
2536			bss->max_listen_interval = atoi(pos);
2537		} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
2538			bss->disable_pmksa_caching = atoi(pos);
2539		} else if (os_strcmp(buf, "okc") == 0) {
2540			bss->okc = atoi(pos);
2541#ifdef CONFIG_WPS
2542		} else if (os_strcmp(buf, "wps_state") == 0) {
2543			bss->wps_state = atoi(pos);
2544			if (bss->wps_state < 0 || bss->wps_state > 2) {
2545				wpa_printf(MSG_ERROR, "Line %d: invalid "
2546					   "wps_state", line);
2547				errors++;
2548			}
2549		} else if (os_strcmp(buf, "ap_setup_locked") == 0) {
2550			bss->ap_setup_locked = atoi(pos);
2551		} else if (os_strcmp(buf, "uuid") == 0) {
2552			if (uuid_str2bin(pos, bss->uuid)) {
2553				wpa_printf(MSG_ERROR, "Line %d: invalid UUID",
2554					   line);
2555				errors++;
2556			}
2557		} else if (os_strcmp(buf, "wps_pin_requests") == 0) {
2558			os_free(bss->wps_pin_requests);
2559			bss->wps_pin_requests = os_strdup(pos);
2560		} else if (os_strcmp(buf, "device_name") == 0) {
2561			if (os_strlen(pos) > 32) {
2562				wpa_printf(MSG_ERROR, "Line %d: Too long "
2563					   "device_name", line);
2564				errors++;
2565			}
2566			os_free(bss->device_name);
2567			bss->device_name = os_strdup(pos);
2568		} else if (os_strcmp(buf, "manufacturer") == 0) {
2569			if (os_strlen(pos) > 64) {
2570				wpa_printf(MSG_ERROR, "Line %d: Too long "
2571					   "manufacturer", line);
2572				errors++;
2573			}
2574			os_free(bss->manufacturer);
2575			bss->manufacturer = os_strdup(pos);
2576		} else if (os_strcmp(buf, "model_name") == 0) {
2577			if (os_strlen(pos) > 32) {
2578				wpa_printf(MSG_ERROR, "Line %d: Too long "
2579					   "model_name", line);
2580				errors++;
2581			}
2582			os_free(bss->model_name);
2583			bss->model_name = os_strdup(pos);
2584		} else if (os_strcmp(buf, "model_number") == 0) {
2585			if (os_strlen(pos) > 32) {
2586				wpa_printf(MSG_ERROR, "Line %d: Too long "
2587					   "model_number", line);
2588				errors++;
2589			}
2590			os_free(bss->model_number);
2591			bss->model_number = os_strdup(pos);
2592		} else if (os_strcmp(buf, "serial_number") == 0) {
2593			if (os_strlen(pos) > 32) {
2594				wpa_printf(MSG_ERROR, "Line %d: Too long "
2595					   "serial_number", line);
2596				errors++;
2597			}
2598			os_free(bss->serial_number);
2599			bss->serial_number = os_strdup(pos);
2600		} else if (os_strcmp(buf, "device_type") == 0) {
2601			if (wps_dev_type_str2bin(pos, bss->device_type))
2602				errors++;
2603		} else if (os_strcmp(buf, "config_methods") == 0) {
2604			os_free(bss->config_methods);
2605			bss->config_methods = os_strdup(pos);
2606		} else if (os_strcmp(buf, "os_version") == 0) {
2607			if (hexstr2bin(pos, bss->os_version, 4)) {
2608				wpa_printf(MSG_ERROR, "Line %d: invalid "
2609					   "os_version", line);
2610				errors++;
2611			}
2612		} else if (os_strcmp(buf, "ap_pin") == 0) {
2613			os_free(bss->ap_pin);
2614			bss->ap_pin = os_strdup(pos);
2615		} else if (os_strcmp(buf, "skip_cred_build") == 0) {
2616			bss->skip_cred_build = atoi(pos);
2617		} else if (os_strcmp(buf, "extra_cred") == 0) {
2618			os_free(bss->extra_cred);
2619			bss->extra_cred =
2620				(u8 *) os_readfile(pos, &bss->extra_cred_len);
2621			if (bss->extra_cred == NULL) {
2622				wpa_printf(MSG_ERROR, "Line %d: could not "
2623					   "read Credentials from '%s'",
2624					   line, pos);
2625				errors++;
2626			}
2627		} else if (os_strcmp(buf, "wps_cred_processing") == 0) {
2628			bss->wps_cred_processing = atoi(pos);
2629		} else if (os_strcmp(buf, "ap_settings") == 0) {
2630			os_free(bss->ap_settings);
2631			bss->ap_settings =
2632				(u8 *) os_readfile(pos, &bss->ap_settings_len);
2633			if (bss->ap_settings == NULL) {
2634				wpa_printf(MSG_ERROR, "Line %d: could not "
2635					   "read AP Settings from '%s'",
2636					   line, pos);
2637				errors++;
2638			}
2639		} else if (os_strcmp(buf, "upnp_iface") == 0) {
2640			bss->upnp_iface = os_strdup(pos);
2641		} else if (os_strcmp(buf, "friendly_name") == 0) {
2642			os_free(bss->friendly_name);
2643			bss->friendly_name = os_strdup(pos);
2644		} else if (os_strcmp(buf, "manufacturer_url") == 0) {
2645			os_free(bss->manufacturer_url);
2646			bss->manufacturer_url = os_strdup(pos);
2647		} else if (os_strcmp(buf, "model_description") == 0) {
2648			os_free(bss->model_description);
2649			bss->model_description = os_strdup(pos);
2650		} else if (os_strcmp(buf, "model_url") == 0) {
2651			os_free(bss->model_url);
2652			bss->model_url = os_strdup(pos);
2653		} else if (os_strcmp(buf, "upc") == 0) {
2654			os_free(bss->upc);
2655			bss->upc = os_strdup(pos);
2656		} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
2657			bss->pbc_in_m1 = atoi(pos);
2658#ifdef CONFIG_WPS_NFC
2659		} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
2660			bss->wps_nfc_dev_pw_id = atoi(pos);
2661			if (bss->wps_nfc_dev_pw_id < 0x10 ||
2662			    bss->wps_nfc_dev_pw_id > 0xffff) {
2663				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2664					   "wps_nfc_dev_pw_id value", line);
2665				errors++;
2666			}
2667		} else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
2668			wpabuf_free(bss->wps_nfc_dh_pubkey);
2669			bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos);
2670		} else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
2671			wpabuf_free(bss->wps_nfc_dh_privkey);
2672			bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos);
2673		} else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
2674			wpabuf_free(bss->wps_nfc_dev_pw);
2675			bss->wps_nfc_dev_pw = hostapd_parse_bin(pos);
2676#endif /* CONFIG_WPS_NFC */
2677#endif /* CONFIG_WPS */
2678#ifdef CONFIG_P2P_MANAGER
2679		} else if (os_strcmp(buf, "manage_p2p") == 0) {
2680			int manage = atoi(pos);
2681			if (manage)
2682				bss->p2p |= P2P_MANAGE;
2683			else
2684				bss->p2p &= ~P2P_MANAGE;
2685		} else if (os_strcmp(buf, "allow_cross_connection") == 0) {
2686			if (atoi(pos))
2687				bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
2688			else
2689				bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
2690#endif /* CONFIG_P2P_MANAGER */
2691		} else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
2692			bss->disassoc_low_ack = atoi(pos);
2693		} else if (os_strcmp(buf, "tdls_prohibit") == 0) {
2694			int val = atoi(pos);
2695			if (val)
2696				bss->tdls |= TDLS_PROHIBIT;
2697			else
2698				bss->tdls &= ~TDLS_PROHIBIT;
2699		} else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
2700			int val = atoi(pos);
2701			if (val)
2702				bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
2703			else
2704				bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
2705#ifdef CONFIG_RSN_TESTING
2706		} else if (os_strcmp(buf, "rsn_testing") == 0) {
2707			extern int rsn_testing;
2708			rsn_testing = atoi(pos);
2709#endif /* CONFIG_RSN_TESTING */
2710		} else if (os_strcmp(buf, "time_advertisement") == 0) {
2711			bss->time_advertisement = atoi(pos);
2712		} else if (os_strcmp(buf, "time_zone") == 0) {
2713			size_t tz_len = os_strlen(pos);
2714			if (tz_len < 4 || tz_len > 255) {
2715				wpa_printf(MSG_DEBUG, "Line %d: invalid "
2716					   "time_zone", line);
2717				errors++;
2718				return errors;
2719			}
2720			os_free(bss->time_zone);
2721			bss->time_zone = os_strdup(pos);
2722			if (bss->time_zone == NULL)
2723				errors++;
2724#ifdef CONFIG_WNM
2725		} else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
2726			bss->wnm_sleep_mode = atoi(pos);
2727		} else if (os_strcmp(buf, "bss_transition") == 0) {
2728			bss->bss_transition = atoi(pos);
2729#endif /* CONFIG_WNM */
2730#ifdef CONFIG_INTERWORKING
2731		} else if (os_strcmp(buf, "interworking") == 0) {
2732			bss->interworking = atoi(pos);
2733		} else if (os_strcmp(buf, "access_network_type") == 0) {
2734			bss->access_network_type = atoi(pos);
2735			if (bss->access_network_type < 0 ||
2736			    bss->access_network_type > 15) {
2737				wpa_printf(MSG_ERROR, "Line %d: invalid "
2738					   "access_network_type", line);
2739				errors++;
2740			}
2741		} else if (os_strcmp(buf, "internet") == 0) {
2742			bss->internet = atoi(pos);
2743		} else if (os_strcmp(buf, "asra") == 0) {
2744			bss->asra = atoi(pos);
2745		} else if (os_strcmp(buf, "esr") == 0) {
2746			bss->esr = atoi(pos);
2747		} else if (os_strcmp(buf, "uesa") == 0) {
2748			bss->uesa = atoi(pos);
2749		} else if (os_strcmp(buf, "venue_group") == 0) {
2750			bss->venue_group = atoi(pos);
2751			bss->venue_info_set = 1;
2752		} else if (os_strcmp(buf, "venue_type") == 0) {
2753			bss->venue_type = atoi(pos);
2754			bss->venue_info_set = 1;
2755		} else if (os_strcmp(buf, "hessid") == 0) {
2756			if (hwaddr_aton(pos, bss->hessid)) {
2757				wpa_printf(MSG_ERROR, "Line %d: invalid "
2758					   "hessid", line);
2759				errors++;
2760			}
2761		} else if (os_strcmp(buf, "roaming_consortium") == 0) {
2762			if (parse_roaming_consortium(bss, pos, line) < 0)
2763				errors++;
2764		} else if (os_strcmp(buf, "venue_name") == 0) {
2765			if (parse_venue_name(bss, pos, line) < 0)
2766				errors++;
2767		} else if (os_strcmp(buf, "network_auth_type") == 0) {
2768			u8 auth_type;
2769			u16 redirect_url_len;
2770			if (hexstr2bin(pos, &auth_type, 1)) {
2771				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2772					   "network_auth_type '%s'",
2773					   line, pos);
2774				errors++;
2775				return errors;
2776			}
2777			if (auth_type == 0 || auth_type == 2)
2778				redirect_url_len = os_strlen(pos + 2);
2779			else
2780				redirect_url_len = 0;
2781			os_free(bss->network_auth_type);
2782			bss->network_auth_type =
2783				os_malloc(redirect_url_len + 3 + 1);
2784			if (bss->network_auth_type == NULL) {
2785				errors++;
2786				return errors;
2787			}
2788			*bss->network_auth_type = auth_type;
2789			WPA_PUT_LE16(bss->network_auth_type + 1,
2790				     redirect_url_len);
2791			if (redirect_url_len)
2792				os_memcpy(bss->network_auth_type + 3,
2793					  pos + 2, redirect_url_len);
2794			bss->network_auth_type_len = 3 + redirect_url_len;
2795		} else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
2796			if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1))
2797			{
2798				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2799					   "ipaddr_type_availability '%s'",
2800					   line, pos);
2801				bss->ipaddr_type_configured = 0;
2802				errors++;
2803				return errors;
2804			}
2805			bss->ipaddr_type_configured = 1;
2806		} else if (os_strcmp(buf, "domain_name") == 0) {
2807			int j, num_domains, domain_len, domain_list_len = 0;
2808			char *tok_start, *tok_prev;
2809			u8 *domain_list, *domain_ptr;
2810
2811			domain_list_len = os_strlen(pos) + 1;
2812			domain_list = os_malloc(domain_list_len);
2813			if (domain_list == NULL) {
2814				errors++;
2815				return errors;
2816			}
2817
2818			domain_ptr = domain_list;
2819			tok_prev = pos;
2820			num_domains = 1;
2821			while ((tok_prev = os_strchr(tok_prev, ','))) {
2822				num_domains++;
2823				tok_prev++;
2824			}
2825			tok_prev = pos;
2826			for (j = 0; j < num_domains; j++) {
2827				tok_start = os_strchr(tok_prev, ',');
2828				if (tok_start) {
2829					domain_len = tok_start - tok_prev;
2830					*domain_ptr = domain_len;
2831					os_memcpy(domain_ptr + 1, tok_prev,
2832						  domain_len);
2833					domain_ptr += domain_len + 1;
2834					tok_prev = ++tok_start;
2835				} else {
2836					domain_len = os_strlen(tok_prev);
2837					*domain_ptr = domain_len;
2838					os_memcpy(domain_ptr + 1, tok_prev,
2839						  domain_len);
2840					domain_ptr += domain_len + 1;
2841				}
2842			}
2843
2844			os_free(bss->domain_name);
2845			bss->domain_name = domain_list;
2846			bss->domain_name_len = domain_list_len;
2847		} else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
2848			if (parse_3gpp_cell_net(bss, pos, line) < 0)
2849				errors++;
2850		} else if (os_strcmp(buf, "nai_realm") == 0) {
2851			if (parse_nai_realm(bss, pos, line) < 0)
2852				errors++;
2853		} else if (os_strcmp(buf, "gas_frag_limit") == 0) {
2854			bss->gas_frag_limit = atoi(pos);
2855		} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
2856			bss->gas_comeback_delay = atoi(pos);
2857#endif /* CONFIG_INTERWORKING */
2858#ifdef CONFIG_RADIUS_TEST
2859		} else if (os_strcmp(buf, "dump_msk_file") == 0) {
2860			os_free(bss->dump_msk_file);
2861			bss->dump_msk_file = os_strdup(pos);
2862#endif /* CONFIG_RADIUS_TEST */
2863#ifdef CONFIG_HS20
2864		} else if (os_strcmp(buf, "hs20") == 0) {
2865			bss->hs20 = atoi(pos);
2866		} else if (os_strcmp(buf, "disable_dgaf") == 0) {
2867			bss->disable_dgaf = atoi(pos);
2868		} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
2869			if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
2870				errors++;
2871		} else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
2872			if (hs20_parse_wan_metrics(bss, pos, line) < 0) {
2873				errors++;
2874				return errors;
2875			}
2876		} else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
2877			if (hs20_parse_conn_capab(bss, pos, line) < 0) {
2878				errors++;
2879				return errors;
2880			}
2881		} else if (os_strcmp(buf, "hs20_operating_class") == 0) {
2882			u8 *oper_class;
2883			size_t oper_class_len;
2884			oper_class_len = os_strlen(pos);
2885			if (oper_class_len < 2 || (oper_class_len & 0x01)) {
2886				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2887					   "hs20_operating_class '%s'",
2888					   line, pos);
2889				errors++;
2890				return errors;
2891			}
2892			oper_class_len /= 2;
2893			oper_class = os_malloc(oper_class_len);
2894			if (oper_class == NULL) {
2895				errors++;
2896				return errors;
2897			}
2898			if (hexstr2bin(pos, oper_class, oper_class_len)) {
2899				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2900					   "hs20_operating_class '%s'",
2901					   line, pos);
2902				os_free(oper_class);
2903				errors++;
2904				return errors;
2905			}
2906			os_free(bss->hs20_operating_class);
2907			bss->hs20_operating_class = oper_class;
2908			bss->hs20_operating_class_len = oper_class_len;
2909#endif /* CONFIG_HS20 */
2910		} else if (os_strcmp(buf, "vendor_elements") == 0) {
2911			struct wpabuf *elems;
2912			size_t len = os_strlen(pos);
2913			if (len & 0x01) {
2914				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2915					   "vendor_elements '%s'", line, pos);
2916				return 1;
2917			}
2918			len /= 2;
2919			if (len == 0) {
2920				wpabuf_free(bss->vendor_elements);
2921				bss->vendor_elements = NULL;
2922				return 0;
2923			}
2924
2925			elems = wpabuf_alloc(len);
2926			if (elems == NULL)
2927				return 1;
2928
2929			if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
2930				wpabuf_free(elems);
2931				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2932					   "vendor_elements '%s'", line, pos);
2933				return 1;
2934			}
2935
2936			wpabuf_free(bss->vendor_elements);
2937			bss->vendor_elements = elems;
2938		} else {
2939			wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
2940				   "item '%s'", line, buf);
2941			errors++;
2942		}
2943	}
2944
2945	return errors;
2946}
2947
2948
2949static void hostapd_set_security_params(struct hostapd_bss_config *bss)
2950{
2951	int pairwise;
2952
2953	if (bss->individual_wep_key_len == 0) {
2954		/* individual keys are not use; can use key idx0 for
2955		 * broadcast keys */
2956		bss->broadcast_key_idx_min = 0;
2957	}
2958
2959	/* Select group cipher based on the enabled pairwise cipher
2960	 * suites */
2961	pairwise = 0;
2962	if (bss->wpa & 1)
2963		pairwise |= bss->wpa_pairwise;
2964	if (bss->wpa & 2) {
2965		if (bss->rsn_pairwise == 0)
2966			bss->rsn_pairwise = bss->wpa_pairwise;
2967		pairwise |= bss->rsn_pairwise;
2968	}
2969	if (pairwise & WPA_CIPHER_TKIP)
2970		bss->wpa_group = WPA_CIPHER_TKIP;
2971	else if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ==
2972		 WPA_CIPHER_GCMP)
2973		bss->wpa_group = WPA_CIPHER_GCMP;
2974	else
2975		bss->wpa_group = WPA_CIPHER_CCMP;
2976
2977	bss->radius->auth_server = bss->radius->auth_servers;
2978	bss->radius->acct_server = bss->radius->acct_servers;
2979
2980	if (bss->wpa && bss->ieee802_1x) {
2981		bss->ssid.security_policy = SECURITY_WPA;
2982	} else if (bss->wpa) {
2983		bss->ssid.security_policy = SECURITY_WPA_PSK;
2984	} else if (bss->ieee802_1x) {
2985		int cipher = WPA_CIPHER_NONE;
2986		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
2987		bss->ssid.wep.default_len = bss->default_wep_key_len;
2988		if (bss->default_wep_key_len)
2989			cipher = bss->default_wep_key_len >= 13 ?
2990				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
2991		bss->wpa_group = cipher;
2992		bss->wpa_pairwise = cipher;
2993		bss->rsn_pairwise = cipher;
2994	} else if (bss->ssid.wep.keys_set) {
2995		int cipher = WPA_CIPHER_WEP40;
2996		if (bss->ssid.wep.len[0] >= 13)
2997			cipher = WPA_CIPHER_WEP104;
2998		bss->ssid.security_policy = SECURITY_STATIC_WEP;
2999		bss->wpa_group = cipher;
3000		bss->wpa_pairwise = cipher;
3001		bss->rsn_pairwise = cipher;
3002	} else {
3003		bss->ssid.security_policy = SECURITY_PLAINTEXT;
3004		bss->wpa_group = WPA_CIPHER_NONE;
3005		bss->wpa_pairwise = WPA_CIPHER_NONE;
3006		bss->rsn_pairwise = WPA_CIPHER_NONE;
3007	}
3008}
3009
3010
3011/**
3012 * hostapd_config_read - Read and parse a configuration file
3013 * @fname: Configuration file name (including path, if needed)
3014 * Returns: Allocated configuration data structure
3015 */
3016struct hostapd_config * hostapd_config_read(const char *fname)
3017{
3018	struct hostapd_config *conf;
3019	struct hostapd_bss_config *bss;
3020	FILE *f;
3021	char buf[512], *pos;
3022	int line = 0;
3023	int errors = 0;
3024	size_t i;
3025
3026	f = fopen(fname, "r");
3027	if (f == NULL) {
3028		wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
3029			   "for reading.", fname);
3030		return NULL;
3031	}
3032
3033	conf = hostapd_config_defaults();
3034	if (conf == NULL) {
3035		fclose(f);
3036		return NULL;
3037	}
3038
3039	/* set default driver based on configuration */
3040	conf->driver = wpa_drivers[0];
3041	if (conf->driver == NULL) {
3042		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
3043		hostapd_config_free(conf);
3044		fclose(f);
3045		return NULL;
3046	}
3047
3048	bss = conf->last_bss = conf->bss;
3049
3050	while (fgets(buf, sizeof(buf), f)) {
3051		bss = conf->last_bss;
3052		line++;
3053
3054		if (buf[0] == '#')
3055			continue;
3056		pos = buf;
3057		while (*pos != '\0') {
3058			if (*pos == '\n') {
3059				*pos = '\0';
3060				break;
3061			}
3062			pos++;
3063		}
3064		if (buf[0] == '\0')
3065			continue;
3066
3067		pos = os_strchr(buf, '=');
3068		if (pos == NULL) {
3069			wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
3070				   line, buf);
3071			errors++;
3072			continue;
3073		}
3074		*pos = '\0';
3075		pos++;
3076		errors += hostapd_config_fill(conf, bss, buf, pos, line);
3077	}
3078
3079	fclose(f);
3080
3081	for (i = 0; i < conf->num_bss; i++)
3082		hostapd_set_security_params(&conf->bss[i]);
3083
3084	if (hostapd_config_check(conf))
3085		errors++;
3086
3087#ifndef WPA_IGNORE_CONFIG_ERRORS
3088	if (errors) {
3089		wpa_printf(MSG_ERROR, "%d errors found in configuration file "
3090			   "'%s'", errors, fname);
3091		hostapd_config_free(conf);
3092		conf = NULL;
3093	}
3094#endif /* WPA_IGNORE_CONFIG_ERRORS */
3095
3096	return conf;
3097}
3098
3099
3100int hostapd_set_iface(struct hostapd_config *conf,
3101		      struct hostapd_bss_config *bss, char *field, char *value)
3102{
3103	int errors;
3104	size_t i;
3105
3106	errors = hostapd_config_fill(conf, bss, field, value, 0);
3107	if (errors) {
3108		wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
3109			   "to value '%s'", field, value);
3110		return -1;
3111	}
3112
3113	for (i = 0; i < conf->num_bss; i++)
3114		hostapd_set_security_params(&conf->bss[i]);
3115
3116	if (hostapd_config_check(conf)) {
3117		wpa_printf(MSG_ERROR, "Configuration check failed");
3118		return -1;
3119	}
3120
3121	return 0;
3122}
3123