config_file.c revision d5e4923d04122f81300fa68fb07d64ede28fd44d
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, "macaddr_acl") == 0) {
1784			bss->macaddr_acl = atoi(pos);
1785			if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
1786			    bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
1787			    bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1788				wpa_printf(MSG_ERROR, "Line %d: unknown "
1789					   "macaddr_acl %d",
1790					   line, bss->macaddr_acl);
1791			}
1792		} else if (os_strcmp(buf, "accept_mac_file") == 0) {
1793			if (hostapd_config_read_maclist(pos, &bss->accept_mac,
1794							&bss->num_accept_mac))
1795			{
1796				wpa_printf(MSG_ERROR, "Line %d: Failed to "
1797					   "read accept_mac_file '%s'",
1798					   line, pos);
1799				errors++;
1800			}
1801		} else if (os_strcmp(buf, "deny_mac_file") == 0) {
1802			if (hostapd_config_read_maclist(pos, &bss->deny_mac,
1803							&bss->num_deny_mac)) {
1804				wpa_printf(MSG_ERROR, "Line %d: Failed to "
1805					   "read deny_mac_file '%s'",
1806					   line, pos);
1807				errors++;
1808			}
1809		} else if (os_strcmp(buf, "wds_sta") == 0) {
1810			bss->wds_sta = atoi(pos);
1811		} else if (os_strcmp(buf, "ap_isolate") == 0) {
1812			bss->isolate = atoi(pos);
1813		} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
1814			bss->ap_max_inactivity = atoi(pos);
1815		} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
1816			bss->skip_inactivity_poll = atoi(pos);
1817		} else if (os_strcmp(buf, "country_code") == 0) {
1818			os_memcpy(conf->country, pos, 2);
1819			/* FIX: make this configurable */
1820			conf->country[2] = ' ';
1821		} else if (os_strcmp(buf, "ieee80211d") == 0) {
1822			conf->ieee80211d = atoi(pos);
1823		} else if (os_strcmp(buf, "ieee8021x") == 0) {
1824			bss->ieee802_1x = atoi(pos);
1825		} else if (os_strcmp(buf, "eapol_version") == 0) {
1826			bss->eapol_version = atoi(pos);
1827			if (bss->eapol_version < 1 ||
1828			    bss->eapol_version > 2) {
1829				wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL "
1830					   "version (%d): '%s'.",
1831					   line, bss->eapol_version, pos);
1832				errors++;
1833			} else
1834				wpa_printf(MSG_DEBUG, "eapol_version=%d",
1835					   bss->eapol_version);
1836#ifdef EAP_SERVER
1837		} else if (os_strcmp(buf, "eap_authenticator") == 0) {
1838			bss->eap_server = atoi(pos);
1839			wpa_printf(MSG_ERROR, "Line %d: obsolete "
1840				   "eap_authenticator used; this has been "
1841				   "renamed to eap_server", line);
1842		} else if (os_strcmp(buf, "eap_server") == 0) {
1843			bss->eap_server = atoi(pos);
1844		} else if (os_strcmp(buf, "eap_user_file") == 0) {
1845			if (hostapd_config_read_eap_user(pos, bss))
1846				errors++;
1847		} else if (os_strcmp(buf, "ca_cert") == 0) {
1848			os_free(bss->ca_cert);
1849			bss->ca_cert = os_strdup(pos);
1850		} else if (os_strcmp(buf, "server_cert") == 0) {
1851			os_free(bss->server_cert);
1852			bss->server_cert = os_strdup(pos);
1853		} else if (os_strcmp(buf, "private_key") == 0) {
1854			os_free(bss->private_key);
1855			bss->private_key = os_strdup(pos);
1856		} else if (os_strcmp(buf, "private_key_passwd") == 0) {
1857			os_free(bss->private_key_passwd);
1858			bss->private_key_passwd = os_strdup(pos);
1859		} else if (os_strcmp(buf, "check_crl") == 0) {
1860			bss->check_crl = atoi(pos);
1861		} else if (os_strcmp(buf, "dh_file") == 0) {
1862			os_free(bss->dh_file);
1863			bss->dh_file = os_strdup(pos);
1864		} else if (os_strcmp(buf, "fragment_size") == 0) {
1865			bss->fragment_size = atoi(pos);
1866#ifdef EAP_SERVER_FAST
1867		} else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
1868			os_free(bss->pac_opaque_encr_key);
1869			bss->pac_opaque_encr_key = os_malloc(16);
1870			if (bss->pac_opaque_encr_key == NULL) {
1871				wpa_printf(MSG_ERROR, "Line %d: No memory for "
1872					   "pac_opaque_encr_key", line);
1873				errors++;
1874			} else if (hexstr2bin(pos, bss->pac_opaque_encr_key,
1875					      16)) {
1876				wpa_printf(MSG_ERROR, "Line %d: Invalid "
1877					   "pac_opaque_encr_key", line);
1878				errors++;
1879			}
1880		} else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
1881			size_t idlen = os_strlen(pos);
1882			if (idlen & 1) {
1883				wpa_printf(MSG_ERROR, "Line %d: Invalid "
1884					   "eap_fast_a_id", line);
1885				errors++;
1886			} else {
1887				os_free(bss->eap_fast_a_id);
1888				bss->eap_fast_a_id = os_malloc(idlen / 2);
1889				if (bss->eap_fast_a_id == NULL ||
1890				    hexstr2bin(pos, bss->eap_fast_a_id,
1891					       idlen / 2)) {
1892					wpa_printf(MSG_ERROR, "Line %d: "
1893						   "Failed to parse "
1894						   "eap_fast_a_id", line);
1895					errors++;
1896				} else
1897					bss->eap_fast_a_id_len = idlen / 2;
1898			}
1899		} else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
1900			os_free(bss->eap_fast_a_id_info);
1901			bss->eap_fast_a_id_info = os_strdup(pos);
1902		} else if (os_strcmp(buf, "eap_fast_prov") == 0) {
1903			bss->eap_fast_prov = atoi(pos);
1904		} else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
1905			bss->pac_key_lifetime = atoi(pos);
1906		} else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
1907			bss->pac_key_refresh_time = atoi(pos);
1908#endif /* EAP_SERVER_FAST */
1909#ifdef EAP_SERVER_SIM
1910		} else if (os_strcmp(buf, "eap_sim_db") == 0) {
1911			os_free(bss->eap_sim_db);
1912			bss->eap_sim_db = os_strdup(pos);
1913		} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
1914			bss->eap_sim_aka_result_ind = atoi(pos);
1915#endif /* EAP_SERVER_SIM */
1916#ifdef EAP_SERVER_TNC
1917		} else if (os_strcmp(buf, "tnc") == 0) {
1918			bss->tnc = atoi(pos);
1919#endif /* EAP_SERVER_TNC */
1920#ifdef EAP_SERVER_PWD
1921		} else if (os_strcmp(buf, "pwd_group") == 0) {
1922			bss->pwd_group = atoi(pos);
1923#endif /* EAP_SERVER_PWD */
1924#endif /* EAP_SERVER */
1925		} else if (os_strcmp(buf, "eap_message") == 0) {
1926			char *term;
1927			bss->eap_req_id_text = os_strdup(pos);
1928			if (bss->eap_req_id_text == NULL) {
1929				wpa_printf(MSG_ERROR, "Line %d: Failed to "
1930					   "allocate memory for "
1931					   "eap_req_id_text", line);
1932				errors++;
1933				return errors;
1934			}
1935			bss->eap_req_id_text_len =
1936				os_strlen(bss->eap_req_id_text);
1937			term = os_strstr(bss->eap_req_id_text, "\\0");
1938			if (term) {
1939				*term++ = '\0';
1940				os_memmove(term, term + 1,
1941					   bss->eap_req_id_text_len -
1942					   (term - bss->eap_req_id_text) - 1);
1943				bss->eap_req_id_text_len--;
1944			}
1945		} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
1946			bss->default_wep_key_len = atoi(pos);
1947			if (bss->default_wep_key_len > 13) {
1948				wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
1949					   "key len %lu (= %lu bits)", line,
1950					   (unsigned long)
1951					   bss->default_wep_key_len,
1952					   (unsigned long)
1953					   bss->default_wep_key_len * 8);
1954				errors++;
1955			}
1956		} else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
1957			bss->individual_wep_key_len = atoi(pos);
1958			if (bss->individual_wep_key_len < 0 ||
1959			    bss->individual_wep_key_len > 13) {
1960				wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
1961					   "key len %d (= %d bits)", line,
1962					   bss->individual_wep_key_len,
1963					   bss->individual_wep_key_len * 8);
1964				errors++;
1965			}
1966		} else if (os_strcmp(buf, "wep_rekey_period") == 0) {
1967			bss->wep_rekeying_period = atoi(pos);
1968			if (bss->wep_rekeying_period < 0) {
1969				wpa_printf(MSG_ERROR, "Line %d: invalid "
1970					   "period %d",
1971					   line, bss->wep_rekeying_period);
1972				errors++;
1973			}
1974		} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
1975			bss->eap_reauth_period = atoi(pos);
1976			if (bss->eap_reauth_period < 0) {
1977				wpa_printf(MSG_ERROR, "Line %d: invalid "
1978					   "period %d",
1979					   line, bss->eap_reauth_period);
1980				errors++;
1981			}
1982		} else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
1983			bss->eapol_key_index_workaround = atoi(pos);
1984#ifdef CONFIG_IAPP
1985		} else if (os_strcmp(buf, "iapp_interface") == 0) {
1986			bss->ieee802_11f = 1;
1987			os_strlcpy(bss->iapp_iface, pos,
1988				   sizeof(bss->iapp_iface));
1989#endif /* CONFIG_IAPP */
1990		} else if (os_strcmp(buf, "own_ip_addr") == 0) {
1991			if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
1992				wpa_printf(MSG_ERROR, "Line %d: invalid IP "
1993					   "address '%s'", line, pos);
1994				errors++;
1995			}
1996		} else if (os_strcmp(buf, "nas_identifier") == 0) {
1997			bss->nas_identifier = os_strdup(pos);
1998#ifndef CONFIG_NO_RADIUS
1999		} else if (os_strcmp(buf, "auth_server_addr") == 0) {
2000			if (hostapd_config_read_radius_addr(
2001				    &bss->radius->auth_servers,
2002				    &bss->radius->num_auth_servers, pos, 1812,
2003				    &bss->radius->auth_server)) {
2004				wpa_printf(MSG_ERROR, "Line %d: invalid IP "
2005					   "address '%s'", line, pos);
2006				errors++;
2007			}
2008		} else if (bss->radius->auth_server &&
2009			   os_strcmp(buf, "auth_server_port") == 0) {
2010			bss->radius->auth_server->port = atoi(pos);
2011		} else if (bss->radius->auth_server &&
2012			   os_strcmp(buf, "auth_server_shared_secret") == 0) {
2013			int len = os_strlen(pos);
2014			if (len == 0) {
2015				/* RFC 2865, Ch. 3 */
2016				wpa_printf(MSG_ERROR, "Line %d: empty shared "
2017					   "secret is not allowed.", line);
2018				errors++;
2019			}
2020			bss->radius->auth_server->shared_secret =
2021				(u8 *) os_strdup(pos);
2022			bss->radius->auth_server->shared_secret_len = len;
2023		} else if (os_strcmp(buf, "acct_server_addr") == 0) {
2024			if (hostapd_config_read_radius_addr(
2025				    &bss->radius->acct_servers,
2026				    &bss->radius->num_acct_servers, pos, 1813,
2027				    &bss->radius->acct_server)) {
2028				wpa_printf(MSG_ERROR, "Line %d: invalid IP "
2029					   "address '%s'", line, pos);
2030				errors++;
2031			}
2032		} else if (bss->radius->acct_server &&
2033			   os_strcmp(buf, "acct_server_port") == 0) {
2034			bss->radius->acct_server->port = atoi(pos);
2035		} else if (bss->radius->acct_server &&
2036			   os_strcmp(buf, "acct_server_shared_secret") == 0) {
2037			int len = os_strlen(pos);
2038			if (len == 0) {
2039				/* RFC 2865, Ch. 3 */
2040				wpa_printf(MSG_ERROR, "Line %d: empty shared "
2041					   "secret is not allowed.", line);
2042				errors++;
2043			}
2044			bss->radius->acct_server->shared_secret =
2045				(u8 *) os_strdup(pos);
2046			bss->radius->acct_server->shared_secret_len = len;
2047		} else if (os_strcmp(buf, "radius_retry_primary_interval") ==
2048			   0) {
2049			bss->radius->retry_primary_interval = atoi(pos);
2050		} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0)
2051		{
2052			bss->acct_interim_interval = atoi(pos);
2053		} else if (os_strcmp(buf, "radius_request_cui") == 0) {
2054			bss->radius_request_cui = atoi(pos);
2055		} else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
2056			struct hostapd_radius_attr *attr, *a;
2057			attr = hostapd_parse_radius_attr(pos);
2058			if (attr == NULL) {
2059				wpa_printf(MSG_ERROR, "Line %d: invalid "
2060					   "radius_auth_req_attr", line);
2061				errors++;
2062			} else if (bss->radius_auth_req_attr == NULL) {
2063				bss->radius_auth_req_attr = attr;
2064			} else {
2065				a = bss->radius_auth_req_attr;
2066				while (a->next)
2067					a = a->next;
2068				a->next = attr;
2069			}
2070		} else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
2071			struct hostapd_radius_attr *attr, *a;
2072			attr = hostapd_parse_radius_attr(pos);
2073			if (attr == NULL) {
2074				wpa_printf(MSG_ERROR, "Line %d: invalid "
2075					   "radius_acct_req_attr", line);
2076				errors++;
2077			} else if (bss->radius_acct_req_attr == NULL) {
2078				bss->radius_acct_req_attr = attr;
2079			} else {
2080				a = bss->radius_acct_req_attr;
2081				while (a->next)
2082					a = a->next;
2083				a->next = attr;
2084			}
2085		} else if (os_strcmp(buf, "radius_das_port") == 0) {
2086			bss->radius_das_port = atoi(pos);
2087		} else if (os_strcmp(buf, "radius_das_client") == 0) {
2088			if (hostapd_parse_das_client(bss, pos) < 0) {
2089				wpa_printf(MSG_ERROR, "Line %d: invalid "
2090					   "DAS client", line);
2091				errors++;
2092			}
2093		} else if (os_strcmp(buf, "radius_das_time_window") == 0) {
2094			bss->radius_das_time_window = atoi(pos);
2095		} else if (os_strcmp(buf, "radius_das_require_event_timestamp")
2096			   == 0) {
2097			bss->radius_das_require_event_timestamp = atoi(pos);
2098#endif /* CONFIG_NO_RADIUS */
2099		} else if (os_strcmp(buf, "auth_algs") == 0) {
2100			bss->auth_algs = atoi(pos);
2101			if (bss->auth_algs == 0) {
2102				wpa_printf(MSG_ERROR, "Line %d: no "
2103					   "authentication algorithms allowed",
2104					   line);
2105				errors++;
2106			}
2107		} else if (os_strcmp(buf, "max_num_sta") == 0) {
2108			bss->max_num_sta = atoi(pos);
2109			if (bss->max_num_sta < 0 ||
2110			    bss->max_num_sta > MAX_STA_COUNT) {
2111				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2112					   "max_num_sta=%d; allowed range "
2113					   "0..%d", line, bss->max_num_sta,
2114					   MAX_STA_COUNT);
2115				errors++;
2116			}
2117		} else if (os_strcmp(buf, "wpa") == 0) {
2118			bss->wpa = atoi(pos);
2119		} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
2120			bss->wpa_group_rekey = atoi(pos);
2121		} else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
2122			bss->wpa_strict_rekey = atoi(pos);
2123		} else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
2124			bss->wpa_gmk_rekey = atoi(pos);
2125		} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
2126			bss->wpa_ptk_rekey = atoi(pos);
2127		} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
2128			int len = os_strlen(pos);
2129			if (len < 8 || len > 63) {
2130				wpa_printf(MSG_ERROR, "Line %d: invalid WPA "
2131					   "passphrase length %d (expected "
2132					   "8..63)", line, len);
2133				errors++;
2134			} else {
2135				os_free(bss->ssid.wpa_passphrase);
2136				bss->ssid.wpa_passphrase = os_strdup(pos);
2137				os_free(bss->ssid.wpa_psk);
2138				bss->ssid.wpa_psk = NULL;
2139			}
2140		} else if (os_strcmp(buf, "wpa_psk") == 0) {
2141			os_free(bss->ssid.wpa_psk);
2142			bss->ssid.wpa_psk =
2143				os_zalloc(sizeof(struct hostapd_wpa_psk));
2144			if (bss->ssid.wpa_psk == NULL)
2145				errors++;
2146			else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk,
2147					    PMK_LEN) ||
2148				 pos[PMK_LEN * 2] != '\0') {
2149				wpa_printf(MSG_ERROR, "Line %d: Invalid PSK "
2150					   "'%s'.", line, pos);
2151				errors++;
2152			} else {
2153				bss->ssid.wpa_psk->group = 1;
2154				os_free(bss->ssid.wpa_passphrase);
2155				bss->ssid.wpa_passphrase = NULL;
2156			}
2157		} else if (os_strcmp(buf, "wpa_psk_file") == 0) {
2158			os_free(bss->ssid.wpa_psk_file);
2159			bss->ssid.wpa_psk_file = os_strdup(pos);
2160			if (!bss->ssid.wpa_psk_file) {
2161				wpa_printf(MSG_ERROR, "Line %d: allocation "
2162					   "failed", line);
2163				errors++;
2164			}
2165		} else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
2166			bss->wpa_key_mgmt =
2167				hostapd_config_parse_key_mgmt(line, pos);
2168			if (bss->wpa_key_mgmt == -1)
2169				errors++;
2170		} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
2171			bss->wpa_psk_radius = atoi(pos);
2172			if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
2173			    bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
2174			    bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
2175				wpa_printf(MSG_ERROR, "Line %d: unknown "
2176					   "wpa_psk_radius %d",
2177					   line, bss->wpa_psk_radius);
2178				errors++;
2179			}
2180		} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
2181			bss->wpa_pairwise =
2182				hostapd_config_parse_cipher(line, pos);
2183			if (bss->wpa_pairwise == -1 ||
2184			    bss->wpa_pairwise == 0)
2185				errors++;
2186			else if (bss->wpa_pairwise &
2187				 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
2188				  WPA_CIPHER_WEP104)) {
2189				wpa_printf(MSG_ERROR, "Line %d: unsupported "
2190					   "pairwise cipher suite '%s'",
2191					   bss->wpa_pairwise, pos);
2192				errors++;
2193			}
2194		} else if (os_strcmp(buf, "rsn_pairwise") == 0) {
2195			bss->rsn_pairwise =
2196				hostapd_config_parse_cipher(line, pos);
2197			if (bss->rsn_pairwise == -1 ||
2198			    bss->rsn_pairwise == 0)
2199				errors++;
2200			else if (bss->rsn_pairwise &
2201				 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
2202				  WPA_CIPHER_WEP104)) {
2203				wpa_printf(MSG_ERROR, "Line %d: unsupported "
2204					   "pairwise cipher suite '%s'",
2205					   bss->rsn_pairwise, pos);
2206				errors++;
2207			}
2208#ifdef CONFIG_RSN_PREAUTH
2209		} else if (os_strcmp(buf, "rsn_preauth") == 0) {
2210			bss->rsn_preauth = atoi(pos);
2211		} else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
2212			bss->rsn_preauth_interfaces = os_strdup(pos);
2213#endif /* CONFIG_RSN_PREAUTH */
2214#ifdef CONFIG_PEERKEY
2215		} else if (os_strcmp(buf, "peerkey") == 0) {
2216			bss->peerkey = atoi(pos);
2217#endif /* CONFIG_PEERKEY */
2218#ifdef CONFIG_IEEE80211R
2219		} else if (os_strcmp(buf, "mobility_domain") == 0) {
2220			if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
2221			    hexstr2bin(pos, bss->mobility_domain,
2222				       MOBILITY_DOMAIN_ID_LEN) != 0) {
2223				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2224					   "mobility_domain '%s'", line, pos);
2225				errors++;
2226				return errors;
2227			}
2228		} else if (os_strcmp(buf, "r1_key_holder") == 0) {
2229			if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
2230			    hexstr2bin(pos, bss->r1_key_holder,
2231				       FT_R1KH_ID_LEN) != 0) {
2232				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2233					   "r1_key_holder '%s'", line, pos);
2234				errors++;
2235				return errors;
2236			}
2237		} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
2238			bss->r0_key_lifetime = atoi(pos);
2239		} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
2240			bss->reassociation_deadline = atoi(pos);
2241		} else if (os_strcmp(buf, "r0kh") == 0) {
2242			if (add_r0kh(bss, pos) < 0) {
2243				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2244					   "r0kh '%s'", line, pos);
2245				errors++;
2246				return errors;
2247			}
2248		} else if (os_strcmp(buf, "r1kh") == 0) {
2249			if (add_r1kh(bss, pos) < 0) {
2250				wpa_printf(MSG_DEBUG, "Line %d: Invalid "
2251					   "r1kh '%s'", line, pos);
2252				errors++;
2253				return errors;
2254			}
2255		} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
2256			bss->pmk_r1_push = atoi(pos);
2257		} else if (os_strcmp(buf, "ft_over_ds") == 0) {
2258			bss->ft_over_ds = atoi(pos);
2259#endif /* CONFIG_IEEE80211R */
2260#ifndef CONFIG_NO_CTRL_IFACE
2261		} else if (os_strcmp(buf, "ctrl_interface") == 0) {
2262			os_free(bss->ctrl_interface);
2263			bss->ctrl_interface = os_strdup(pos);
2264		} else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
2265#ifndef CONFIG_NATIVE_WINDOWS
2266			struct group *grp;
2267			char *endp;
2268			const char *group = pos;
2269
2270			grp = getgrnam(group);
2271			if (grp) {
2272				bss->ctrl_interface_gid = grp->gr_gid;
2273				bss->ctrl_interface_gid_set = 1;
2274				wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
2275					   " (from group name '%s')",
2276					   bss->ctrl_interface_gid, group);
2277				return errors;
2278			}
2279
2280			/* Group name not found - try to parse this as gid */
2281			bss->ctrl_interface_gid = strtol(group, &endp, 10);
2282			if (*group == '\0' || *endp != '\0') {
2283				wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
2284					   "'%s'", line, group);
2285				errors++;
2286				return errors;
2287			}
2288			bss->ctrl_interface_gid_set = 1;
2289			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
2290				   bss->ctrl_interface_gid);
2291#endif /* CONFIG_NATIVE_WINDOWS */
2292#endif /* CONFIG_NO_CTRL_IFACE */
2293#ifdef RADIUS_SERVER
2294		} else if (os_strcmp(buf, "radius_server_clients") == 0) {
2295			os_free(bss->radius_server_clients);
2296			bss->radius_server_clients = os_strdup(pos);
2297		} else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
2298			bss->radius_server_auth_port = atoi(pos);
2299		} else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
2300			bss->radius_server_ipv6 = atoi(pos);
2301#endif /* RADIUS_SERVER */
2302		} else if (os_strcmp(buf, "test_socket") == 0) {
2303			os_free(bss->test_socket);
2304			bss->test_socket = os_strdup(pos);
2305		} else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
2306			bss->use_pae_group_addr = atoi(pos);
2307		} else if (os_strcmp(buf, "hw_mode") == 0) {
2308			if (os_strcmp(pos, "a") == 0)
2309				conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
2310			else if (os_strcmp(pos, "b") == 0)
2311				conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
2312			else if (os_strcmp(pos, "g") == 0)
2313				conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
2314			else {
2315				wpa_printf(MSG_ERROR, "Line %d: unknown "
2316					   "hw_mode '%s'", line, pos);
2317				errors++;
2318			}
2319		} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
2320			if (os_strcmp(pos, "a") == 0)
2321				bss->wps_rf_bands = WPS_RF_50GHZ;
2322			else if (os_strcmp(pos, "g") == 0 ||
2323				 os_strcmp(pos, "b") == 0)
2324				bss->wps_rf_bands = WPS_RF_24GHZ;
2325			else if (os_strcmp(pos, "ag") == 0 ||
2326				 os_strcmp(pos, "ga") == 0)
2327				bss->wps_rf_bands =
2328					WPS_RF_24GHZ | WPS_RF_50GHZ;
2329			else {
2330				wpa_printf(MSG_ERROR, "Line %d: unknown "
2331					   "wps_rf_band '%s'", line, pos);
2332				errors++;
2333			}
2334		} else if (os_strcmp(buf, "channel") == 0) {
2335			conf->channel = atoi(pos);
2336		} else if (os_strcmp(buf, "beacon_int") == 0) {
2337			int val = atoi(pos);
2338			/* MIB defines range as 1..65535, but very small values
2339			 * cause problems with the current implementation.
2340			 * Since it is unlikely that this small numbers are
2341			 * useful in real life scenarios, do not allow beacon
2342			 * period to be set below 15 TU. */
2343			if (val < 15 || val > 65535) {
2344				wpa_printf(MSG_ERROR, "Line %d: invalid "
2345					   "beacon_int %d (expected "
2346					   "15..65535)", line, val);
2347				errors++;
2348			} else
2349				conf->beacon_int = val;
2350		} else if (os_strcmp(buf, "dtim_period") == 0) {
2351			bss->dtim_period = atoi(pos);
2352			if (bss->dtim_period < 1 || bss->dtim_period > 255) {
2353				wpa_printf(MSG_ERROR, "Line %d: invalid "
2354					   "dtim_period %d",
2355					   line, bss->dtim_period);
2356				errors++;
2357			}
2358		} else if (os_strcmp(buf, "rts_threshold") == 0) {
2359			conf->rts_threshold = atoi(pos);
2360			if (conf->rts_threshold < 0 ||
2361			    conf->rts_threshold > 2347) {
2362				wpa_printf(MSG_ERROR, "Line %d: invalid "
2363					   "rts_threshold %d",
2364					   line, conf->rts_threshold);
2365				errors++;
2366			}
2367		} else if (os_strcmp(buf, "fragm_threshold") == 0) {
2368			conf->fragm_threshold = atoi(pos);
2369			if (conf->fragm_threshold < 256 ||
2370			    conf->fragm_threshold > 2346) {
2371				wpa_printf(MSG_ERROR, "Line %d: invalid "
2372					   "fragm_threshold %d",
2373					   line, conf->fragm_threshold);
2374				errors++;
2375			}
2376		} else if (os_strcmp(buf, "send_probe_response") == 0) {
2377			int val = atoi(pos);
2378			if (val != 0 && val != 1) {
2379				wpa_printf(MSG_ERROR, "Line %d: invalid "
2380					   "send_probe_response %d (expected "
2381					   "0 or 1)", line, val);
2382			} else
2383				conf->send_probe_response = val;
2384		} else if (os_strcmp(buf, "supported_rates") == 0) {
2385			if (hostapd_parse_rates(&conf->supported_rates, pos)) {
2386				wpa_printf(MSG_ERROR, "Line %d: invalid rate "
2387					   "list", line);
2388				errors++;
2389			}
2390		} else if (os_strcmp(buf, "basic_rates") == 0) {
2391			if (hostapd_parse_rates(&conf->basic_rates, pos)) {
2392				wpa_printf(MSG_ERROR, "Line %d: invalid rate "
2393					   "list", line);
2394				errors++;
2395			}
2396		} else if (os_strcmp(buf, "preamble") == 0) {
2397			if (atoi(pos))
2398				conf->preamble = SHORT_PREAMBLE;
2399			else
2400				conf->preamble = LONG_PREAMBLE;
2401		} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
2402			bss->ignore_broadcast_ssid = atoi(pos);
2403		} else if (os_strcmp(buf, "wep_default_key") == 0) {
2404			bss->ssid.wep.idx = atoi(pos);
2405			if (bss->ssid.wep.idx > 3) {
2406				wpa_printf(MSG_ERROR, "Invalid "
2407					   "wep_default_key index %d",
2408					   bss->ssid.wep.idx);
2409				errors++;
2410			}
2411		} else if (os_strcmp(buf, "wep_key0") == 0 ||
2412			   os_strcmp(buf, "wep_key1") == 0 ||
2413			   os_strcmp(buf, "wep_key2") == 0 ||
2414			   os_strcmp(buf, "wep_key3") == 0) {
2415			if (hostapd_config_read_wep(&bss->ssid.wep,
2416						    buf[7] - '0', pos)) {
2417				wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
2418					   "key '%s'", line, buf);
2419				errors++;
2420			}
2421#ifndef CONFIG_NO_VLAN
2422		} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
2423			bss->ssid.dynamic_vlan = atoi(pos);
2424		} else if (os_strcmp(buf, "vlan_file") == 0) {
2425			if (hostapd_config_read_vlan_file(bss, pos)) {
2426				wpa_printf(MSG_ERROR, "Line %d: failed to "
2427					   "read VLAN file '%s'", line, pos);
2428				errors++;
2429			}
2430		} else if (os_strcmp(buf, "vlan_naming") == 0) {
2431			bss->ssid.vlan_naming = atoi(pos);
2432			if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
2433			    bss->ssid.vlan_naming < 0) {
2434				wpa_printf(MSG_ERROR, "Line %d: invalid "
2435					   "naming scheme %d", line,
2436                                           bss->ssid.vlan_naming);
2437				errors++;
2438                        }
2439#ifdef CONFIG_FULL_DYNAMIC_VLAN
2440		} else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
2441			bss->ssid.vlan_tagged_interface = os_strdup(pos);
2442#endif /* CONFIG_FULL_DYNAMIC_VLAN */
2443#endif /* CONFIG_NO_VLAN */
2444		} else if (os_strcmp(buf, "ap_table_max_size") == 0) {
2445			conf->ap_table_max_size = atoi(pos);
2446		} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
2447			conf->ap_table_expiration_time = atoi(pos);
2448		} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
2449			if (hostapd_config_tx_queue(conf, buf, pos)) {
2450				wpa_printf(MSG_ERROR, "Line %d: invalid TX "
2451					   "queue item", line);
2452				errors++;
2453			}
2454		} else if (os_strcmp(buf, "wme_enabled") == 0 ||
2455			   os_strcmp(buf, "wmm_enabled") == 0) {
2456			bss->wmm_enabled = atoi(pos);
2457		} else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
2458			bss->wmm_uapsd = atoi(pos);
2459		} else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
2460			   os_strncmp(buf, "wmm_ac_", 7) == 0) {
2461			if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf,
2462						  pos)) {
2463				wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
2464					   "ac item", line);
2465				errors++;
2466			}
2467		} else if (os_strcmp(buf, "bss") == 0) {
2468			if (hostapd_config_bss(conf, pos)) {
2469				wpa_printf(MSG_ERROR, "Line %d: invalid bss "
2470					   "item", line);
2471				errors++;
2472			}
2473		} else if (os_strcmp(buf, "bssid") == 0) {
2474			if (hwaddr_aton(pos, bss->bssid)) {
2475				wpa_printf(MSG_ERROR, "Line %d: invalid bssid "
2476					   "item", line);
2477				errors++;
2478			}
2479#ifdef CONFIG_IEEE80211W
2480		} else if (os_strcmp(buf, "ieee80211w") == 0) {
2481			bss->ieee80211w = atoi(pos);
2482		} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
2483			bss->assoc_sa_query_max_timeout = atoi(pos);
2484			if (bss->assoc_sa_query_max_timeout == 0) {
2485				wpa_printf(MSG_ERROR, "Line %d: invalid "
2486					   "assoc_sa_query_max_timeout", line);
2487				errors++;
2488			}
2489		} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0)
2490		{
2491			bss->assoc_sa_query_retry_timeout = atoi(pos);
2492			if (bss->assoc_sa_query_retry_timeout == 0) {
2493				wpa_printf(MSG_ERROR, "Line %d: invalid "
2494					   "assoc_sa_query_retry_timeout",
2495					   line);
2496				errors++;
2497			}
2498#endif /* CONFIG_IEEE80211W */
2499#ifdef CONFIG_IEEE80211N
2500		} else if (os_strcmp(buf, "ieee80211n") == 0) {
2501			conf->ieee80211n = atoi(pos);
2502		} else if (os_strcmp(buf, "ht_capab") == 0) {
2503			if (hostapd_config_ht_capab(conf, pos) < 0) {
2504				wpa_printf(MSG_ERROR, "Line %d: invalid "
2505					   "ht_capab", line);
2506				errors++;
2507			}
2508		} else if (os_strcmp(buf, "require_ht") == 0) {
2509			conf->require_ht = atoi(pos);
2510#endif /* CONFIG_IEEE80211N */
2511#ifdef CONFIG_IEEE80211AC
2512		} else if (os_strcmp(buf, "ieee80211ac") == 0) {
2513			conf->ieee80211ac = atoi(pos);
2514		} else if (os_strcmp(buf, "vht_capab") == 0) {
2515			if (hostapd_config_vht_capab(conf, pos) < 0) {
2516				wpa_printf(MSG_ERROR, "Line %d: invalid "
2517					   "vht_capab", line);
2518				errors++;
2519			}
2520		} else if (os_strcmp(buf, "require_vht") == 0) {
2521			conf->require_vht = atoi(pos);
2522		} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
2523			conf->vht_oper_chwidth = atoi(pos);
2524		} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0)
2525		{
2526			conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
2527		} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0)
2528		{
2529			conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
2530#endif /* CONFIG_IEEE80211AC */
2531		} else if (os_strcmp(buf, "max_listen_interval") == 0) {
2532			bss->max_listen_interval = atoi(pos);
2533		} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
2534			bss->disable_pmksa_caching = atoi(pos);
2535		} else if (os_strcmp(buf, "okc") == 0) {
2536			bss->okc = atoi(pos);
2537#ifdef CONFIG_WPS
2538		} else if (os_strcmp(buf, "wps_state") == 0) {
2539			bss->wps_state = atoi(pos);
2540			if (bss->wps_state < 0 || bss->wps_state > 2) {
2541				wpa_printf(MSG_ERROR, "Line %d: invalid "
2542					   "wps_state", line);
2543				errors++;
2544			}
2545		} else if (os_strcmp(buf, "ap_setup_locked") == 0) {
2546			bss->ap_setup_locked = atoi(pos);
2547		} else if (os_strcmp(buf, "uuid") == 0) {
2548			if (uuid_str2bin(pos, bss->uuid)) {
2549				wpa_printf(MSG_ERROR, "Line %d: invalid UUID",
2550					   line);
2551				errors++;
2552			}
2553		} else if (os_strcmp(buf, "wps_pin_requests") == 0) {
2554			os_free(bss->wps_pin_requests);
2555			bss->wps_pin_requests = os_strdup(pos);
2556		} else if (os_strcmp(buf, "device_name") == 0) {
2557			if (os_strlen(pos) > 32) {
2558				wpa_printf(MSG_ERROR, "Line %d: Too long "
2559					   "device_name", line);
2560				errors++;
2561			}
2562			os_free(bss->device_name);
2563			bss->device_name = os_strdup(pos);
2564		} else if (os_strcmp(buf, "manufacturer") == 0) {
2565			if (os_strlen(pos) > 64) {
2566				wpa_printf(MSG_ERROR, "Line %d: Too long "
2567					   "manufacturer", line);
2568				errors++;
2569			}
2570			os_free(bss->manufacturer);
2571			bss->manufacturer = os_strdup(pos);
2572		} else if (os_strcmp(buf, "model_name") == 0) {
2573			if (os_strlen(pos) > 32) {
2574				wpa_printf(MSG_ERROR, "Line %d: Too long "
2575					   "model_name", line);
2576				errors++;
2577			}
2578			os_free(bss->model_name);
2579			bss->model_name = os_strdup(pos);
2580		} else if (os_strcmp(buf, "model_number") == 0) {
2581			if (os_strlen(pos) > 32) {
2582				wpa_printf(MSG_ERROR, "Line %d: Too long "
2583					   "model_number", line);
2584				errors++;
2585			}
2586			os_free(bss->model_number);
2587			bss->model_number = os_strdup(pos);
2588		} else if (os_strcmp(buf, "serial_number") == 0) {
2589			if (os_strlen(pos) > 32) {
2590				wpa_printf(MSG_ERROR, "Line %d: Too long "
2591					   "serial_number", line);
2592				errors++;
2593			}
2594			os_free(bss->serial_number);
2595			bss->serial_number = os_strdup(pos);
2596		} else if (os_strcmp(buf, "device_type") == 0) {
2597			if (wps_dev_type_str2bin(pos, bss->device_type))
2598				errors++;
2599		} else if (os_strcmp(buf, "config_methods") == 0) {
2600			os_free(bss->config_methods);
2601			bss->config_methods = os_strdup(pos);
2602		} else if (os_strcmp(buf, "os_version") == 0) {
2603			if (hexstr2bin(pos, bss->os_version, 4)) {
2604				wpa_printf(MSG_ERROR, "Line %d: invalid "
2605					   "os_version", line);
2606				errors++;
2607			}
2608		} else if (os_strcmp(buf, "ap_pin") == 0) {
2609			os_free(bss->ap_pin);
2610			bss->ap_pin = os_strdup(pos);
2611		} else if (os_strcmp(buf, "skip_cred_build") == 0) {
2612			bss->skip_cred_build = atoi(pos);
2613		} else if (os_strcmp(buf, "extra_cred") == 0) {
2614			os_free(bss->extra_cred);
2615			bss->extra_cred =
2616				(u8 *) os_readfile(pos, &bss->extra_cred_len);
2617			if (bss->extra_cred == NULL) {
2618				wpa_printf(MSG_ERROR, "Line %d: could not "
2619					   "read Credentials from '%s'",
2620					   line, pos);
2621				errors++;
2622			}
2623		} else if (os_strcmp(buf, "wps_cred_processing") == 0) {
2624			bss->wps_cred_processing = atoi(pos);
2625		} else if (os_strcmp(buf, "ap_settings") == 0) {
2626			os_free(bss->ap_settings);
2627			bss->ap_settings =
2628				(u8 *) os_readfile(pos, &bss->ap_settings_len);
2629			if (bss->ap_settings == NULL) {
2630				wpa_printf(MSG_ERROR, "Line %d: could not "
2631					   "read AP Settings from '%s'",
2632					   line, pos);
2633				errors++;
2634			}
2635		} else if (os_strcmp(buf, "upnp_iface") == 0) {
2636			bss->upnp_iface = os_strdup(pos);
2637		} else if (os_strcmp(buf, "friendly_name") == 0) {
2638			os_free(bss->friendly_name);
2639			bss->friendly_name = os_strdup(pos);
2640		} else if (os_strcmp(buf, "manufacturer_url") == 0) {
2641			os_free(bss->manufacturer_url);
2642			bss->manufacturer_url = os_strdup(pos);
2643		} else if (os_strcmp(buf, "model_description") == 0) {
2644			os_free(bss->model_description);
2645			bss->model_description = os_strdup(pos);
2646		} else if (os_strcmp(buf, "model_url") == 0) {
2647			os_free(bss->model_url);
2648			bss->model_url = os_strdup(pos);
2649		} else if (os_strcmp(buf, "upc") == 0) {
2650			os_free(bss->upc);
2651			bss->upc = os_strdup(pos);
2652		} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
2653			bss->pbc_in_m1 = atoi(pos);
2654#ifdef CONFIG_WPS_NFC
2655		} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
2656			bss->wps_nfc_dev_pw_id = atoi(pos);
2657			if (bss->wps_nfc_dev_pw_id < 0x10 ||
2658			    bss->wps_nfc_dev_pw_id > 0xffff) {
2659				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2660					   "wps_nfc_dev_pw_id value", line);
2661				errors++;
2662			}
2663		} else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
2664			wpabuf_free(bss->wps_nfc_dh_pubkey);
2665			bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos);
2666		} else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
2667			wpabuf_free(bss->wps_nfc_dh_privkey);
2668			bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos);
2669		} else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
2670			wpabuf_free(bss->wps_nfc_dev_pw);
2671			bss->wps_nfc_dev_pw = hostapd_parse_bin(pos);
2672#endif /* CONFIG_WPS_NFC */
2673#endif /* CONFIG_WPS */
2674#ifdef CONFIG_P2P_MANAGER
2675		} else if (os_strcmp(buf, "manage_p2p") == 0) {
2676			int manage = atoi(pos);
2677			if (manage)
2678				bss->p2p |= P2P_MANAGE;
2679			else
2680				bss->p2p &= ~P2P_MANAGE;
2681		} else if (os_strcmp(buf, "allow_cross_connection") == 0) {
2682			if (atoi(pos))
2683				bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
2684			else
2685				bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
2686#endif /* CONFIG_P2P_MANAGER */
2687		} else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
2688			bss->disassoc_low_ack = atoi(pos);
2689		} else if (os_strcmp(buf, "tdls_prohibit") == 0) {
2690			int val = atoi(pos);
2691			if (val)
2692				bss->tdls |= TDLS_PROHIBIT;
2693			else
2694				bss->tdls &= ~TDLS_PROHIBIT;
2695		} else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
2696			int val = atoi(pos);
2697			if (val)
2698				bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
2699			else
2700				bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
2701#ifdef CONFIG_RSN_TESTING
2702		} else if (os_strcmp(buf, "rsn_testing") == 0) {
2703			extern int rsn_testing;
2704			rsn_testing = atoi(pos);
2705#endif /* CONFIG_RSN_TESTING */
2706		} else if (os_strcmp(buf, "time_advertisement") == 0) {
2707			bss->time_advertisement = atoi(pos);
2708		} else if (os_strcmp(buf, "time_zone") == 0) {
2709			size_t tz_len = os_strlen(pos);
2710			if (tz_len < 4 || tz_len > 255) {
2711				wpa_printf(MSG_DEBUG, "Line %d: invalid "
2712					   "time_zone", line);
2713				errors++;
2714				return errors;
2715			}
2716			os_free(bss->time_zone);
2717			bss->time_zone = os_strdup(pos);
2718			if (bss->time_zone == NULL)
2719				errors++;
2720#ifdef CONFIG_INTERWORKING
2721		} else if (os_strcmp(buf, "interworking") == 0) {
2722			bss->interworking = atoi(pos);
2723		} else if (os_strcmp(buf, "access_network_type") == 0) {
2724			bss->access_network_type = atoi(pos);
2725			if (bss->access_network_type < 0 ||
2726			    bss->access_network_type > 15) {
2727				wpa_printf(MSG_ERROR, "Line %d: invalid "
2728					   "access_network_type", line);
2729				errors++;
2730			}
2731		} else if (os_strcmp(buf, "internet") == 0) {
2732			bss->internet = atoi(pos);
2733		} else if (os_strcmp(buf, "asra") == 0) {
2734			bss->asra = atoi(pos);
2735		} else if (os_strcmp(buf, "esr") == 0) {
2736			bss->esr = atoi(pos);
2737		} else if (os_strcmp(buf, "uesa") == 0) {
2738			bss->uesa = atoi(pos);
2739		} else if (os_strcmp(buf, "venue_group") == 0) {
2740			bss->venue_group = atoi(pos);
2741			bss->venue_info_set = 1;
2742		} else if (os_strcmp(buf, "venue_type") == 0) {
2743			bss->venue_type = atoi(pos);
2744			bss->venue_info_set = 1;
2745		} else if (os_strcmp(buf, "hessid") == 0) {
2746			if (hwaddr_aton(pos, bss->hessid)) {
2747				wpa_printf(MSG_ERROR, "Line %d: invalid "
2748					   "hessid", line);
2749				errors++;
2750			}
2751		} else if (os_strcmp(buf, "roaming_consortium") == 0) {
2752			if (parse_roaming_consortium(bss, pos, line) < 0)
2753				errors++;
2754		} else if (os_strcmp(buf, "venue_name") == 0) {
2755			if (parse_venue_name(bss, pos, line) < 0)
2756				errors++;
2757		} else if (os_strcmp(buf, "network_auth_type") == 0) {
2758			u8 auth_type;
2759			u16 redirect_url_len;
2760			if (hexstr2bin(pos, &auth_type, 1)) {
2761				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2762					   "network_auth_type '%s'",
2763					   line, pos);
2764				errors++;
2765				return errors;
2766			}
2767			if (auth_type == 0 || auth_type == 2)
2768				redirect_url_len = os_strlen(pos + 2);
2769			else
2770				redirect_url_len = 0;
2771			os_free(bss->network_auth_type);
2772			bss->network_auth_type =
2773				os_malloc(redirect_url_len + 3 + 1);
2774			if (bss->network_auth_type == NULL) {
2775				errors++;
2776				return errors;
2777			}
2778			*bss->network_auth_type = auth_type;
2779			WPA_PUT_LE16(bss->network_auth_type + 1,
2780				     redirect_url_len);
2781			if (redirect_url_len)
2782				os_memcpy(bss->network_auth_type + 3,
2783					  pos + 2, redirect_url_len);
2784			bss->network_auth_type_len = 3 + redirect_url_len;
2785		} else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
2786			if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1))
2787			{
2788				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2789					   "ipaddr_type_availability '%s'",
2790					   line, pos);
2791				bss->ipaddr_type_configured = 0;
2792				errors++;
2793				return errors;
2794			}
2795			bss->ipaddr_type_configured = 1;
2796		} else if (os_strcmp(buf, "domain_name") == 0) {
2797			int j, num_domains, domain_len, domain_list_len = 0;
2798			char *tok_start, *tok_prev;
2799			u8 *domain_list, *domain_ptr;
2800
2801			domain_list_len = os_strlen(pos) + 1;
2802			domain_list = os_malloc(domain_list_len);
2803			if (domain_list == NULL) {
2804				errors++;
2805				return errors;
2806			}
2807
2808			domain_ptr = domain_list;
2809			tok_prev = pos;
2810			num_domains = 1;
2811			while ((tok_prev = os_strchr(tok_prev, ','))) {
2812				num_domains++;
2813				tok_prev++;
2814			}
2815			tok_prev = pos;
2816			for (j = 0; j < num_domains; j++) {
2817				tok_start = os_strchr(tok_prev, ',');
2818				if (tok_start) {
2819					domain_len = tok_start - tok_prev;
2820					*domain_ptr = domain_len;
2821					os_memcpy(domain_ptr + 1, tok_prev,
2822						  domain_len);
2823					domain_ptr += domain_len + 1;
2824					tok_prev = ++tok_start;
2825				} else {
2826					domain_len = os_strlen(tok_prev);
2827					*domain_ptr = domain_len;
2828					os_memcpy(domain_ptr + 1, tok_prev,
2829						  domain_len);
2830					domain_ptr += domain_len + 1;
2831				}
2832			}
2833
2834			os_free(bss->domain_name);
2835			bss->domain_name = domain_list;
2836			bss->domain_name_len = domain_list_len;
2837		} else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
2838			if (parse_3gpp_cell_net(bss, pos, line) < 0)
2839				errors++;
2840		} else if (os_strcmp(buf, "nai_realm") == 0) {
2841			if (parse_nai_realm(bss, pos, line) < 0)
2842				errors++;
2843		} else if (os_strcmp(buf, "gas_frag_limit") == 0) {
2844			bss->gas_frag_limit = atoi(pos);
2845		} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
2846			bss->gas_comeback_delay = atoi(pos);
2847#endif /* CONFIG_INTERWORKING */
2848#ifdef CONFIG_RADIUS_TEST
2849		} else if (os_strcmp(buf, "dump_msk_file") == 0) {
2850			os_free(bss->dump_msk_file);
2851			bss->dump_msk_file = os_strdup(pos);
2852#endif /* CONFIG_RADIUS_TEST */
2853#ifdef CONFIG_HS20
2854		} else if (os_strcmp(buf, "hs20") == 0) {
2855			bss->hs20 = atoi(pos);
2856		} else if (os_strcmp(buf, "disable_dgaf") == 0) {
2857			bss->disable_dgaf = atoi(pos);
2858		} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
2859			if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
2860				errors++;
2861		} else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
2862			if (hs20_parse_wan_metrics(bss, pos, line) < 0) {
2863				errors++;
2864				return errors;
2865			}
2866		} else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
2867			if (hs20_parse_conn_capab(bss, pos, line) < 0) {
2868				errors++;
2869				return errors;
2870			}
2871		} else if (os_strcmp(buf, "hs20_operating_class") == 0) {
2872			u8 *oper_class;
2873			size_t oper_class_len;
2874			oper_class_len = os_strlen(pos);
2875			if (oper_class_len < 2 || (oper_class_len & 0x01)) {
2876				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2877					   "hs20_operating_class '%s'",
2878					   line, pos);
2879				errors++;
2880				return errors;
2881			}
2882			oper_class_len /= 2;
2883			oper_class = os_malloc(oper_class_len);
2884			if (oper_class == NULL) {
2885				errors++;
2886				return errors;
2887			}
2888			if (hexstr2bin(pos, oper_class, oper_class_len)) {
2889				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2890					   "hs20_operating_class '%s'",
2891					   line, pos);
2892				os_free(oper_class);
2893				errors++;
2894				return errors;
2895			}
2896			os_free(bss->hs20_operating_class);
2897			bss->hs20_operating_class = oper_class;
2898			bss->hs20_operating_class_len = oper_class_len;
2899#endif /* CONFIG_HS20 */
2900		} else if (os_strcmp(buf, "vendor_elements") == 0) {
2901			struct wpabuf *elems;
2902			size_t len = os_strlen(pos);
2903			if (len & 0x01) {
2904				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2905					   "vendor_elements '%s'", line, pos);
2906				return 1;
2907			}
2908			len /= 2;
2909			if (len == 0) {
2910				wpabuf_free(bss->vendor_elements);
2911				bss->vendor_elements = NULL;
2912				return 0;
2913			}
2914
2915			elems = wpabuf_alloc(len);
2916			if (elems == NULL)
2917				return 1;
2918
2919			if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
2920				wpabuf_free(elems);
2921				wpa_printf(MSG_ERROR, "Line %d: Invalid "
2922					   "vendor_elements '%s'", line, pos);
2923				return 1;
2924			}
2925
2926			wpabuf_free(bss->vendor_elements);
2927			bss->vendor_elements = elems;
2928		} else {
2929			wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
2930				   "item '%s'", line, buf);
2931			errors++;
2932		}
2933	}
2934
2935	return errors;
2936}
2937
2938
2939static void hostapd_set_security_params(struct hostapd_bss_config *bss)
2940{
2941	int pairwise;
2942
2943	if (bss->individual_wep_key_len == 0) {
2944		/* individual keys are not use; can use key idx0 for
2945		 * broadcast keys */
2946		bss->broadcast_key_idx_min = 0;
2947	}
2948
2949	/* Select group cipher based on the enabled pairwise cipher
2950	 * suites */
2951	pairwise = 0;
2952	if (bss->wpa & 1)
2953		pairwise |= bss->wpa_pairwise;
2954	if (bss->wpa & 2) {
2955		if (bss->rsn_pairwise == 0)
2956			bss->rsn_pairwise = bss->wpa_pairwise;
2957		pairwise |= bss->rsn_pairwise;
2958	}
2959	if (pairwise & WPA_CIPHER_TKIP)
2960		bss->wpa_group = WPA_CIPHER_TKIP;
2961	else if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ==
2962		 WPA_CIPHER_GCMP)
2963		bss->wpa_group = WPA_CIPHER_GCMP;
2964	else
2965		bss->wpa_group = WPA_CIPHER_CCMP;
2966
2967	bss->radius->auth_server = bss->radius->auth_servers;
2968	bss->radius->acct_server = bss->radius->acct_servers;
2969
2970	if (bss->wpa && bss->ieee802_1x) {
2971		bss->ssid.security_policy = SECURITY_WPA;
2972	} else if (bss->wpa) {
2973		bss->ssid.security_policy = SECURITY_WPA_PSK;
2974	} else if (bss->ieee802_1x) {
2975		int cipher = WPA_CIPHER_NONE;
2976		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
2977		bss->ssid.wep.default_len = bss->default_wep_key_len;
2978		if (bss->default_wep_key_len)
2979			cipher = bss->default_wep_key_len >= 13 ?
2980				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
2981		bss->wpa_group = cipher;
2982		bss->wpa_pairwise = cipher;
2983		bss->rsn_pairwise = cipher;
2984	} else if (bss->ssid.wep.keys_set) {
2985		int cipher = WPA_CIPHER_WEP40;
2986		if (bss->ssid.wep.len[0] >= 13)
2987			cipher = WPA_CIPHER_WEP104;
2988		bss->ssid.security_policy = SECURITY_STATIC_WEP;
2989		bss->wpa_group = cipher;
2990		bss->wpa_pairwise = cipher;
2991		bss->rsn_pairwise = cipher;
2992	} else {
2993		bss->ssid.security_policy = SECURITY_PLAINTEXT;
2994		bss->wpa_group = WPA_CIPHER_NONE;
2995		bss->wpa_pairwise = WPA_CIPHER_NONE;
2996		bss->rsn_pairwise = WPA_CIPHER_NONE;
2997	}
2998}
2999
3000
3001/**
3002 * hostapd_config_read - Read and parse a configuration file
3003 * @fname: Configuration file name (including path, if needed)
3004 * Returns: Allocated configuration data structure
3005 */
3006struct hostapd_config * hostapd_config_read(const char *fname)
3007{
3008	struct hostapd_config *conf;
3009	struct hostapd_bss_config *bss;
3010	FILE *f;
3011	char buf[512], *pos;
3012	int line = 0;
3013	int errors = 0;
3014	size_t i;
3015
3016	f = fopen(fname, "r");
3017	if (f == NULL) {
3018		wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
3019			   "for reading.", fname);
3020		return NULL;
3021	}
3022
3023	conf = hostapd_config_defaults();
3024	if (conf == NULL) {
3025		fclose(f);
3026		return NULL;
3027	}
3028
3029	/* set default driver based on configuration */
3030	conf->driver = wpa_drivers[0];
3031	if (conf->driver == NULL) {
3032		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
3033		hostapd_config_free(conf);
3034		fclose(f);
3035		return NULL;
3036	}
3037
3038	bss = conf->last_bss = conf->bss;
3039
3040	while (fgets(buf, sizeof(buf), f)) {
3041		bss = conf->last_bss;
3042		line++;
3043
3044		if (buf[0] == '#')
3045			continue;
3046		pos = buf;
3047		while (*pos != '\0') {
3048			if (*pos == '\n') {
3049				*pos = '\0';
3050				break;
3051			}
3052			pos++;
3053		}
3054		if (buf[0] == '\0')
3055			continue;
3056
3057		pos = os_strchr(buf, '=');
3058		if (pos == NULL) {
3059			wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
3060				   line, buf);
3061			errors++;
3062			continue;
3063		}
3064		*pos = '\0';
3065		pos++;
3066		errors += hostapd_config_fill(conf, bss, buf, pos, line);
3067	}
3068
3069	fclose(f);
3070
3071	for (i = 0; i < conf->num_bss; i++)
3072		hostapd_set_security_params(&conf->bss[i]);
3073
3074	if (hostapd_config_check(conf))
3075		errors++;
3076
3077#ifndef WPA_IGNORE_CONFIG_ERRORS
3078	if (errors) {
3079		wpa_printf(MSG_ERROR, "%d errors found in configuration file "
3080			   "'%s'", errors, fname);
3081		hostapd_config_free(conf);
3082		conf = NULL;
3083	}
3084#endif /* WPA_IGNORE_CONFIG_ERRORS */
3085
3086	return conf;
3087}
3088
3089
3090int hostapd_set_iface(struct hostapd_config *conf,
3091		      struct hostapd_bss_config *bss, char *field, char *value)
3092{
3093	int errors;
3094	size_t i;
3095
3096	errors = hostapd_config_fill(conf, bss, field, value, 0);
3097	if (errors) {
3098		wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
3099			   "to value '%s'", field, value);
3100		return -1;
3101	}
3102
3103	for (i = 0; i < conf->num_bss; i++)
3104		hostapd_set_security_params(&conf->bss[i]);
3105
3106	if (hostapd_config_check(conf)) {
3107		wpa_printf(MSG_ERROR, "Configuration check failed");
3108		return -1;
3109	}
3110
3111	return 0;
3112}
3113