xref: /freebsd/contrib/wpa/hostapd/config_file.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1e28a4053SRui Paulo /*
2e28a4053SRui Paulo  * hostapd / Configuration file parser
3*a90b9d01SCy Schubert  * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
4e28a4053SRui Paulo  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
7e28a4053SRui Paulo  */
8e28a4053SRui Paulo 
9e28a4053SRui Paulo #include "utils/includes.h"
10e28a4053SRui Paulo #ifndef CONFIG_NATIVE_WINDOWS
11e28a4053SRui Paulo #include <grp.h>
12e28a4053SRui Paulo #endif /* CONFIG_NATIVE_WINDOWS */
13e28a4053SRui Paulo 
14e28a4053SRui Paulo #include "utils/common.h"
15e28a4053SRui Paulo #include "utils/uuid.h"
164b72b91aSCy Schubert #include "utils/crc32.h"
17e28a4053SRui Paulo #include "common/ieee802_11_defs.h"
18c1d255d3SCy Schubert #include "common/sae.h"
1985732ac8SCy Schubert #include "crypto/sha256.h"
2085732ac8SCy Schubert #include "crypto/tls.h"
21e28a4053SRui Paulo #include "drivers/driver.h"
22e28a4053SRui Paulo #include "eap_server/eap.h"
23e28a4053SRui Paulo #include "radius/radius_client.h"
24e28a4053SRui Paulo #include "ap/wpa_auth.h"
25e28a4053SRui Paulo #include "ap/ap_config.h"
26e28a4053SRui Paulo #include "config_file.h"
27e28a4053SRui Paulo 
28e28a4053SRui Paulo 
29e28a4053SRui Paulo #ifndef CONFIG_NO_VLAN
hostapd_config_read_vlan_file(struct hostapd_bss_config * bss,const char * fname)30e28a4053SRui Paulo static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
31e28a4053SRui Paulo 					 const char *fname)
32e28a4053SRui Paulo {
33e28a4053SRui Paulo 	FILE *f;
344bc52338SCy Schubert 	char buf[128], *pos, *pos2, *pos3;
35e28a4053SRui Paulo 	int line = 0, vlan_id;
36e28a4053SRui Paulo 	struct hostapd_vlan *vlan;
37e28a4053SRui Paulo 
38e28a4053SRui Paulo 	f = fopen(fname, "r");
39e28a4053SRui Paulo 	if (!f) {
40e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname);
41e28a4053SRui Paulo 		return -1;
42e28a4053SRui Paulo 	}
43e28a4053SRui Paulo 
44e28a4053SRui Paulo 	while (fgets(buf, sizeof(buf), f)) {
45e28a4053SRui Paulo 		line++;
46e28a4053SRui Paulo 
47e28a4053SRui Paulo 		if (buf[0] == '#')
48e28a4053SRui Paulo 			continue;
49e28a4053SRui Paulo 		pos = buf;
50e28a4053SRui Paulo 		while (*pos != '\0') {
51e28a4053SRui Paulo 			if (*pos == '\n') {
52e28a4053SRui Paulo 				*pos = '\0';
53e28a4053SRui Paulo 				break;
54e28a4053SRui Paulo 			}
55e28a4053SRui Paulo 			pos++;
56e28a4053SRui Paulo 		}
57e28a4053SRui Paulo 		if (buf[0] == '\0')
58e28a4053SRui Paulo 			continue;
59e28a4053SRui Paulo 
60e28a4053SRui Paulo 		if (buf[0] == '*') {
61e28a4053SRui Paulo 			vlan_id = VLAN_ID_WILDCARD;
62e28a4053SRui Paulo 			pos = buf + 1;
63e28a4053SRui Paulo 		} else {
64e28a4053SRui Paulo 			vlan_id = strtol(buf, &pos, 10);
65e28a4053SRui Paulo 			if (buf == pos || vlan_id < 1 ||
66e28a4053SRui Paulo 			    vlan_id > MAX_VLAN_ID) {
67e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid VLAN ID at "
68e28a4053SRui Paulo 					   "line %d in '%s'", line, fname);
69e28a4053SRui Paulo 				fclose(f);
70e28a4053SRui Paulo 				return -1;
71e28a4053SRui Paulo 			}
72e28a4053SRui Paulo 		}
73e28a4053SRui Paulo 
74e28a4053SRui Paulo 		while (*pos == ' ' || *pos == '\t')
75e28a4053SRui Paulo 			pos++;
76e28a4053SRui Paulo 		pos2 = pos;
77e28a4053SRui Paulo 		while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
78e28a4053SRui Paulo 			pos2++;
794bc52338SCy Schubert 
804bc52338SCy Schubert 		if (*pos2 != '\0')
814bc52338SCy Schubert 			*(pos2++) = '\0';
824bc52338SCy Schubert 
83e28a4053SRui Paulo 		if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
84e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
85e28a4053SRui Paulo 				   "in '%s'", line, fname);
86e28a4053SRui Paulo 			fclose(f);
87e28a4053SRui Paulo 			return -1;
88e28a4053SRui Paulo 		}
89e28a4053SRui Paulo 
904bc52338SCy Schubert 		while (*pos2 == ' ' || *pos2 == '\t')
914bc52338SCy Schubert 			pos2++;
924bc52338SCy Schubert 		pos3 = pos2;
934bc52338SCy Schubert 		while (*pos3 != ' ' && *pos3 != '\t' && *pos3 != '\0')
944bc52338SCy Schubert 			pos3++;
954bc52338SCy Schubert 		*pos3 = '\0';
964bc52338SCy Schubert 
975b9c547cSRui Paulo 		vlan = os_zalloc(sizeof(*vlan));
98e28a4053SRui Paulo 		if (vlan == NULL) {
99e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "Out of memory while reading "
100e28a4053SRui Paulo 				   "VLAN interfaces from '%s'", fname);
101e28a4053SRui Paulo 			fclose(f);
102e28a4053SRui Paulo 			return -1;
103e28a4053SRui Paulo 		}
104e28a4053SRui Paulo 
105e28a4053SRui Paulo 		vlan->vlan_id = vlan_id;
106780fb4a2SCy Schubert 		vlan->vlan_desc.untagged = vlan_id;
107780fb4a2SCy Schubert 		vlan->vlan_desc.notempty = !!vlan_id;
108e28a4053SRui Paulo 		os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
1094bc52338SCy Schubert 		os_strlcpy(vlan->bridge, pos2, sizeof(vlan->bridge));
1105b9c547cSRui Paulo 		vlan->next = bss->vlan;
111e28a4053SRui Paulo 		bss->vlan = vlan;
112e28a4053SRui Paulo 	}
113e28a4053SRui Paulo 
114e28a4053SRui Paulo 	fclose(f);
115e28a4053SRui Paulo 
116e28a4053SRui Paulo 	return 0;
117e28a4053SRui Paulo }
118e28a4053SRui Paulo #endif /* CONFIG_NO_VLAN */
119e28a4053SRui Paulo 
120e28a4053SRui Paulo 
hostapd_config_read_maclist(const char * fname,struct mac_acl_entry ** acl,int * num)121e28a4053SRui Paulo static int hostapd_config_read_maclist(const char *fname,
122e28a4053SRui Paulo 				       struct mac_acl_entry **acl, int *num)
123e28a4053SRui Paulo {
124e28a4053SRui Paulo 	FILE *f;
125e28a4053SRui Paulo 	char buf[128], *pos;
126e28a4053SRui Paulo 	int line = 0;
127e28a4053SRui Paulo 	u8 addr[ETH_ALEN];
128e28a4053SRui Paulo 	int vlan_id;
129e28a4053SRui Paulo 
130e28a4053SRui Paulo 	f = fopen(fname, "r");
131e28a4053SRui Paulo 	if (!f) {
132e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname);
133e28a4053SRui Paulo 		return -1;
134e28a4053SRui Paulo 	}
135e28a4053SRui Paulo 
136e28a4053SRui Paulo 	while (fgets(buf, sizeof(buf), f)) {
13785732ac8SCy Schubert 		int rem = 0;
1385b9c547cSRui Paulo 
139e28a4053SRui Paulo 		line++;
140e28a4053SRui Paulo 
141e28a4053SRui Paulo 		if (buf[0] == '#')
142e28a4053SRui Paulo 			continue;
143e28a4053SRui Paulo 		pos = buf;
144e28a4053SRui Paulo 		while (*pos != '\0') {
145e28a4053SRui Paulo 			if (*pos == '\n') {
146e28a4053SRui Paulo 				*pos = '\0';
147e28a4053SRui Paulo 				break;
148e28a4053SRui Paulo 			}
149e28a4053SRui Paulo 			pos++;
150e28a4053SRui Paulo 		}
151e28a4053SRui Paulo 		if (buf[0] == '\0')
152e28a4053SRui Paulo 			continue;
1535b9c547cSRui Paulo 		pos = buf;
1545b9c547cSRui Paulo 		if (buf[0] == '-') {
1555b9c547cSRui Paulo 			rem = 1;
1565b9c547cSRui Paulo 			pos++;
1575b9c547cSRui Paulo 		}
158e28a4053SRui Paulo 
1595b9c547cSRui Paulo 		if (hwaddr_aton(pos, addr)) {
160e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
1615b9c547cSRui Paulo 				   "line %d in '%s'", pos, line, fname);
162e28a4053SRui Paulo 			fclose(f);
163e28a4053SRui Paulo 			return -1;
164e28a4053SRui Paulo 		}
165e28a4053SRui Paulo 
1665b9c547cSRui Paulo 		if (rem) {
16785732ac8SCy Schubert 			hostapd_remove_acl_mac(acl, num, addr);
1685b9c547cSRui Paulo 			continue;
1695b9c547cSRui Paulo 		}
170e28a4053SRui Paulo 		vlan_id = 0;
171e28a4053SRui Paulo 		pos = buf;
172e28a4053SRui Paulo 		while (*pos != '\0' && *pos != ' ' && *pos != '\t')
173e28a4053SRui Paulo 			pos++;
174e28a4053SRui Paulo 		while (*pos == ' ' || *pos == '\t')
175e28a4053SRui Paulo 			pos++;
176e28a4053SRui Paulo 		if (*pos != '\0')
177e28a4053SRui Paulo 			vlan_id = atoi(pos);
178e28a4053SRui Paulo 
17985732ac8SCy Schubert 		if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) {
180e28a4053SRui Paulo 			fclose(f);
181e28a4053SRui Paulo 			return -1;
182e28a4053SRui Paulo 		}
183e28a4053SRui Paulo 	}
184e28a4053SRui Paulo 
185e28a4053SRui Paulo 	fclose(f);
186e28a4053SRui Paulo 
18785732ac8SCy Schubert 	if (*acl)
188e28a4053SRui Paulo 		qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
189e28a4053SRui Paulo 
190e28a4053SRui Paulo 	return 0;
191e28a4053SRui Paulo }
192e28a4053SRui Paulo 
193e28a4053SRui Paulo 
194e28a4053SRui Paulo #ifdef EAP_SERVER
19585732ac8SCy Schubert 
hostapd_config_eap_user_salted(struct hostapd_eap_user * user,const char * hash,size_t len,char ** pos,int line,const char * fname)19685732ac8SCy Schubert static int hostapd_config_eap_user_salted(struct hostapd_eap_user *user,
19785732ac8SCy Schubert 					  const char *hash, size_t len,
19885732ac8SCy Schubert 					  char **pos, int line,
19985732ac8SCy Schubert 					  const char *fname)
20085732ac8SCy Schubert {
20185732ac8SCy Schubert 	char *pos2 = *pos;
20285732ac8SCy Schubert 
20385732ac8SCy Schubert 	while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t' && *pos2 != '#')
20485732ac8SCy Schubert 		pos2++;
20585732ac8SCy Schubert 
20685732ac8SCy Schubert 	if (pos2 - *pos < (int) (2 * (len + 1))) { /* at least 1 byte of salt */
20785732ac8SCy Schubert 		wpa_printf(MSG_ERROR,
20885732ac8SCy Schubert 			   "Invalid salted %s hash on line %d in '%s'",
20985732ac8SCy Schubert 			   hash, line, fname);
21085732ac8SCy Schubert 		return -1;
21185732ac8SCy Schubert 	}
21285732ac8SCy Schubert 
21385732ac8SCy Schubert 	user->password = os_malloc(len);
21485732ac8SCy Schubert 	if (!user->password) {
21585732ac8SCy Schubert 		wpa_printf(MSG_ERROR,
21685732ac8SCy Schubert 			   "Failed to allocate memory for salted %s hash",
21785732ac8SCy Schubert 			   hash);
21885732ac8SCy Schubert 		return -1;
21985732ac8SCy Schubert 	}
22085732ac8SCy Schubert 
22185732ac8SCy Schubert 	if (hexstr2bin(*pos, user->password, len) < 0) {
22285732ac8SCy Schubert 		wpa_printf(MSG_ERROR,
22385732ac8SCy Schubert 			   "Invalid salted password on line %d in '%s'",
22485732ac8SCy Schubert 			   line, fname);
22585732ac8SCy Schubert 		return -1;
22685732ac8SCy Schubert 	}
22785732ac8SCy Schubert 	user->password_len = len;
22885732ac8SCy Schubert 	*pos += 2 * len;
22985732ac8SCy Schubert 
23085732ac8SCy Schubert 	user->salt_len = (pos2 - *pos) / 2;
23185732ac8SCy Schubert 	user->salt = os_malloc(user->salt_len);
23285732ac8SCy Schubert 	if (!user->salt) {
23385732ac8SCy Schubert 		wpa_printf(MSG_ERROR,
23485732ac8SCy Schubert 			   "Failed to allocate memory for salted %s hash",
23585732ac8SCy Schubert 			   hash);
23685732ac8SCy Schubert 		return -1;
23785732ac8SCy Schubert 	}
23885732ac8SCy Schubert 
23985732ac8SCy Schubert 	if (hexstr2bin(*pos, user->salt, user->salt_len) < 0) {
24085732ac8SCy Schubert 		wpa_printf(MSG_ERROR,
24185732ac8SCy Schubert 			   "Invalid salt for password on line %d in '%s'",
24285732ac8SCy Schubert 			   line, fname);
24385732ac8SCy Schubert 		return -1;
24485732ac8SCy Schubert 	}
24585732ac8SCy Schubert 
24685732ac8SCy Schubert 	*pos = pos2;
24785732ac8SCy Schubert 	return 0;
24885732ac8SCy Schubert }
24985732ac8SCy Schubert 
25085732ac8SCy Schubert 
hostapd_config_read_eap_user(const char * fname,struct hostapd_bss_config * conf)251e28a4053SRui Paulo static int hostapd_config_read_eap_user(const char *fname,
252e28a4053SRui Paulo 					struct hostapd_bss_config *conf)
253e28a4053SRui Paulo {
254e28a4053SRui Paulo 	FILE *f;
255e28a4053SRui Paulo 	char buf[512], *pos, *start, *pos2;
256e28a4053SRui Paulo 	int line = 0, ret = 0, num_methods;
2575b9c547cSRui Paulo 	struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
258e28a4053SRui Paulo 
259f05cddf9SRui Paulo 	if (os_strncmp(fname, "sqlite:", 7) == 0) {
260325151a3SRui Paulo #ifdef CONFIG_SQLITE
261f05cddf9SRui Paulo 		os_free(conf->eap_user_sqlite);
262f05cddf9SRui Paulo 		conf->eap_user_sqlite = os_strdup(fname + 7);
263f05cddf9SRui Paulo 		return 0;
264325151a3SRui Paulo #else /* CONFIG_SQLITE */
265325151a3SRui Paulo 		wpa_printf(MSG_ERROR,
266325151a3SRui Paulo 			   "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
267325151a3SRui Paulo 		return -1;
268325151a3SRui Paulo #endif /* CONFIG_SQLITE */
269f05cddf9SRui Paulo 	}
270f05cddf9SRui Paulo 
271e28a4053SRui Paulo 	f = fopen(fname, "r");
272e28a4053SRui Paulo 	if (!f) {
273e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname);
274e28a4053SRui Paulo 		return -1;
275e28a4053SRui Paulo 	}
276e28a4053SRui Paulo 
277e28a4053SRui Paulo 	/* Lines: "user" METHOD,METHOD2 "password" (password optional) */
278e28a4053SRui Paulo 	while (fgets(buf, sizeof(buf), f)) {
279e28a4053SRui Paulo 		line++;
280e28a4053SRui Paulo 
281e28a4053SRui Paulo 		if (buf[0] == '#')
282e28a4053SRui Paulo 			continue;
283e28a4053SRui Paulo 		pos = buf;
284e28a4053SRui Paulo 		while (*pos != '\0') {
285e28a4053SRui Paulo 			if (*pos == '\n') {
286e28a4053SRui Paulo 				*pos = '\0';
287e28a4053SRui Paulo 				break;
288e28a4053SRui Paulo 			}
289e28a4053SRui Paulo 			pos++;
290e28a4053SRui Paulo 		}
291e28a4053SRui Paulo 		if (buf[0] == '\0')
292e28a4053SRui Paulo 			continue;
293e28a4053SRui Paulo 
2945b9c547cSRui Paulo #ifndef CONFIG_NO_RADIUS
2955b9c547cSRui Paulo 		if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
2965b9c547cSRui Paulo 			struct hostapd_radius_attr *attr, *a;
2975b9c547cSRui Paulo 			attr = hostapd_parse_radius_attr(buf + 19);
2985b9c547cSRui Paulo 			if (attr == NULL) {
299c1d255d3SCy Schubert 				wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s",
3005b9c547cSRui Paulo 					   buf + 19);
3015b9c547cSRui Paulo 				user = NULL; /* already in the BSS list */
3025b9c547cSRui Paulo 				goto failed;
3035b9c547cSRui Paulo 			}
3045b9c547cSRui Paulo 			if (user->accept_attr == NULL) {
3055b9c547cSRui Paulo 				user->accept_attr = attr;
3065b9c547cSRui Paulo 			} else {
3075b9c547cSRui Paulo 				a = user->accept_attr;
3085b9c547cSRui Paulo 				while (a->next)
3095b9c547cSRui Paulo 					a = a->next;
3105b9c547cSRui Paulo 				a->next = attr;
3115b9c547cSRui Paulo 			}
3125b9c547cSRui Paulo 			continue;
3135b9c547cSRui Paulo 		}
3145b9c547cSRui Paulo #endif /* CONFIG_NO_RADIUS */
3155b9c547cSRui Paulo 
316e28a4053SRui Paulo 		user = NULL;
317e28a4053SRui Paulo 
318e28a4053SRui Paulo 		if (buf[0] != '"' && buf[0] != '*') {
319e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in "
320e28a4053SRui Paulo 				   "start) on line %d in '%s'", line, fname);
321e28a4053SRui Paulo 			goto failed;
322e28a4053SRui Paulo 		}
323e28a4053SRui Paulo 
324e28a4053SRui Paulo 		user = os_zalloc(sizeof(*user));
325e28a4053SRui Paulo 		if (user == NULL) {
326e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "EAP user allocation failed");
327e28a4053SRui Paulo 			goto failed;
328e28a4053SRui Paulo 		}
329e28a4053SRui Paulo 		user->force_version = -1;
330e28a4053SRui Paulo 
331e28a4053SRui Paulo 		if (buf[0] == '*') {
332e28a4053SRui Paulo 			pos = buf;
333e28a4053SRui Paulo 		} else {
334e28a4053SRui Paulo 			pos = buf + 1;
335e28a4053SRui Paulo 			start = pos;
336e28a4053SRui Paulo 			while (*pos != '"' && *pos != '\0')
337e28a4053SRui Paulo 				pos++;
338e28a4053SRui Paulo 			if (*pos == '\0') {
339e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid EAP identity "
340e28a4053SRui Paulo 					   "(no \" in end) on line %d in '%s'",
341e28a4053SRui Paulo 					   line, fname);
342e28a4053SRui Paulo 				goto failed;
343e28a4053SRui Paulo 			}
344e28a4053SRui Paulo 
34585732ac8SCy Schubert 			user->identity = os_memdup(start, pos - start);
346e28a4053SRui Paulo 			if (user->identity == NULL) {
347e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Failed to allocate "
348e28a4053SRui Paulo 					   "memory for EAP identity");
349e28a4053SRui Paulo 				goto failed;
350e28a4053SRui Paulo 			}
351e28a4053SRui Paulo 			user->identity_len = pos - start;
352e28a4053SRui Paulo 
353e28a4053SRui Paulo 			if (pos[0] == '"' && pos[1] == '*') {
354e28a4053SRui Paulo 				user->wildcard_prefix = 1;
355e28a4053SRui Paulo 				pos++;
356e28a4053SRui Paulo 			}
357e28a4053SRui Paulo 		}
358e28a4053SRui Paulo 		pos++;
359e28a4053SRui Paulo 		while (*pos == ' ' || *pos == '\t')
360e28a4053SRui Paulo 			pos++;
361e28a4053SRui Paulo 
362e28a4053SRui Paulo 		if (*pos == '\0') {
363e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "No EAP method on line %d in "
364e28a4053SRui Paulo 				   "'%s'", line, fname);
365e28a4053SRui Paulo 			goto failed;
366e28a4053SRui Paulo 		}
367e28a4053SRui Paulo 
368e28a4053SRui Paulo 		start = pos;
369e28a4053SRui Paulo 		while (*pos != ' ' && *pos != '\t' && *pos != '\0')
370e28a4053SRui Paulo 			pos++;
371e28a4053SRui Paulo 		if (*pos == '\0') {
372e28a4053SRui Paulo 			pos = NULL;
373e28a4053SRui Paulo 		} else {
374e28a4053SRui Paulo 			*pos = '\0';
375e28a4053SRui Paulo 			pos++;
376e28a4053SRui Paulo 		}
377e28a4053SRui Paulo 		num_methods = 0;
378e28a4053SRui Paulo 		while (*start) {
379e28a4053SRui Paulo 			char *pos3 = os_strchr(start, ',');
380e28a4053SRui Paulo 			if (pos3) {
381e28a4053SRui Paulo 				*pos3++ = '\0';
382e28a4053SRui Paulo 			}
383e28a4053SRui Paulo 			user->methods[num_methods].method =
384e28a4053SRui Paulo 				eap_server_get_type(
385e28a4053SRui Paulo 					start,
386e28a4053SRui Paulo 					&user->methods[num_methods].vendor);
387e28a4053SRui Paulo 			if (user->methods[num_methods].vendor ==
388e28a4053SRui Paulo 			    EAP_VENDOR_IETF &&
389e28a4053SRui Paulo 			    user->methods[num_methods].method == EAP_TYPE_NONE)
390e28a4053SRui Paulo 			{
391e28a4053SRui Paulo 				if (os_strcmp(start, "TTLS-PAP") == 0) {
392e28a4053SRui Paulo 					user->ttls_auth |= EAP_TTLS_AUTH_PAP;
393e28a4053SRui Paulo 					goto skip_eap;
394e28a4053SRui Paulo 				}
395e28a4053SRui Paulo 				if (os_strcmp(start, "TTLS-CHAP") == 0) {
396e28a4053SRui Paulo 					user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
397e28a4053SRui Paulo 					goto skip_eap;
398e28a4053SRui Paulo 				}
399e28a4053SRui Paulo 				if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
400e28a4053SRui Paulo 					user->ttls_auth |=
401e28a4053SRui Paulo 						EAP_TTLS_AUTH_MSCHAP;
402e28a4053SRui Paulo 					goto skip_eap;
403e28a4053SRui Paulo 				}
404e28a4053SRui Paulo 				if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
405e28a4053SRui Paulo 					user->ttls_auth |=
406e28a4053SRui Paulo 						EAP_TTLS_AUTH_MSCHAPV2;
407e28a4053SRui Paulo 					goto skip_eap;
408e28a4053SRui Paulo 				}
4095b9c547cSRui Paulo 				if (os_strcmp(start, "MACACL") == 0) {
4105b9c547cSRui Paulo 					user->macacl = 1;
4115b9c547cSRui Paulo 					goto skip_eap;
4125b9c547cSRui Paulo 				}
413e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Unsupported EAP type "
414e28a4053SRui Paulo 					   "'%s' on line %d in '%s'",
415e28a4053SRui Paulo 					   start, line, fname);
416e28a4053SRui Paulo 				goto failed;
417e28a4053SRui Paulo 			}
418e28a4053SRui Paulo 
419e28a4053SRui Paulo 			num_methods++;
420f05cddf9SRui Paulo 			if (num_methods >= EAP_MAX_METHODS)
421e28a4053SRui Paulo 				break;
422e28a4053SRui Paulo 		skip_eap:
423e28a4053SRui Paulo 			if (pos3 == NULL)
424e28a4053SRui Paulo 				break;
425e28a4053SRui Paulo 			start = pos3;
426e28a4053SRui Paulo 		}
4275b9c547cSRui Paulo 		if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) {
428e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "No EAP types configured on "
429e28a4053SRui Paulo 				   "line %d in '%s'", line, fname);
430e28a4053SRui Paulo 			goto failed;
431e28a4053SRui Paulo 		}
432e28a4053SRui Paulo 
433e28a4053SRui Paulo 		if (pos == NULL)
434e28a4053SRui Paulo 			goto done;
435e28a4053SRui Paulo 
436e28a4053SRui Paulo 		while (*pos == ' ' || *pos == '\t')
437e28a4053SRui Paulo 			pos++;
438e28a4053SRui Paulo 		if (*pos == '\0')
439e28a4053SRui Paulo 			goto done;
440e28a4053SRui Paulo 
441e28a4053SRui Paulo 		if (os_strncmp(pos, "[ver=0]", 7) == 0) {
442e28a4053SRui Paulo 			user->force_version = 0;
443e28a4053SRui Paulo 			goto done;
444e28a4053SRui Paulo 		}
445e28a4053SRui Paulo 
446e28a4053SRui Paulo 		if (os_strncmp(pos, "[ver=1]", 7) == 0) {
447e28a4053SRui Paulo 			user->force_version = 1;
448e28a4053SRui Paulo 			goto done;
449e28a4053SRui Paulo 		}
450e28a4053SRui Paulo 
451e28a4053SRui Paulo 		if (os_strncmp(pos, "[2]", 3) == 0) {
452e28a4053SRui Paulo 			user->phase2 = 1;
453e28a4053SRui Paulo 			goto done;
454e28a4053SRui Paulo 		}
455e28a4053SRui Paulo 
456e28a4053SRui Paulo 		if (*pos == '"') {
457e28a4053SRui Paulo 			pos++;
458e28a4053SRui Paulo 			start = pos;
459e28a4053SRui Paulo 			while (*pos != '"' && *pos != '\0')
460e28a4053SRui Paulo 				pos++;
461e28a4053SRui Paulo 			if (*pos == '\0') {
462e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid EAP password "
463e28a4053SRui Paulo 					   "(no \" in end) on line %d in '%s'",
464e28a4053SRui Paulo 					   line, fname);
465e28a4053SRui Paulo 				goto failed;
466e28a4053SRui Paulo 			}
467e28a4053SRui Paulo 
46885732ac8SCy Schubert 			user->password = os_memdup(start, pos - start);
469e28a4053SRui Paulo 			if (user->password == NULL) {
470e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Failed to allocate "
471e28a4053SRui Paulo 					   "memory for EAP password");
472e28a4053SRui Paulo 				goto failed;
473e28a4053SRui Paulo 			}
474e28a4053SRui Paulo 			user->password_len = pos - start;
475e28a4053SRui Paulo 
476e28a4053SRui Paulo 			pos++;
477e28a4053SRui Paulo 		} else if (os_strncmp(pos, "hash:", 5) == 0) {
478e28a4053SRui Paulo 			pos += 5;
479e28a4053SRui Paulo 			pos2 = pos;
480e28a4053SRui Paulo 			while (*pos2 != '\0' && *pos2 != ' ' &&
481e28a4053SRui Paulo 			       *pos2 != '\t' && *pos2 != '#')
482e28a4053SRui Paulo 				pos2++;
483e28a4053SRui Paulo 			if (pos2 - pos != 32) {
484e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid password hash "
485e28a4053SRui Paulo 					   "on line %d in '%s'", line, fname);
486e28a4053SRui Paulo 				goto failed;
487e28a4053SRui Paulo 			}
488e28a4053SRui Paulo 			user->password = os_malloc(16);
489e28a4053SRui Paulo 			if (user->password == NULL) {
490e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Failed to allocate "
491e28a4053SRui Paulo 					   "memory for EAP password hash");
492e28a4053SRui Paulo 				goto failed;
493e28a4053SRui Paulo 			}
494e28a4053SRui Paulo 			if (hexstr2bin(pos, user->password, 16) < 0) {
495e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid hash password "
496e28a4053SRui Paulo 					   "on line %d in '%s'", line, fname);
497e28a4053SRui Paulo 				goto failed;
498e28a4053SRui Paulo 			}
499e28a4053SRui Paulo 			user->password_len = 16;
500e28a4053SRui Paulo 			user->password_hash = 1;
501e28a4053SRui Paulo 			pos = pos2;
50285732ac8SCy Schubert 		} else if (os_strncmp(pos, "ssha1:", 6) == 0) {
50385732ac8SCy Schubert 			pos += 6;
50485732ac8SCy Schubert 			if (hostapd_config_eap_user_salted(user, "sha1", 20,
50585732ac8SCy Schubert 							   &pos,
50685732ac8SCy Schubert 							   line, fname) < 0)
50785732ac8SCy Schubert 				goto failed;
50885732ac8SCy Schubert 		} else if (os_strncmp(pos, "ssha256:", 8) == 0) {
50985732ac8SCy Schubert 			pos += 8;
51085732ac8SCy Schubert 			if (hostapd_config_eap_user_salted(user, "sha256", 32,
51185732ac8SCy Schubert 							   &pos,
51285732ac8SCy Schubert 							   line, fname) < 0)
51385732ac8SCy Schubert 				goto failed;
51485732ac8SCy Schubert 		} else if (os_strncmp(pos, "ssha512:", 8) == 0) {
51585732ac8SCy Schubert 			pos += 8;
51685732ac8SCy Schubert 			if (hostapd_config_eap_user_salted(user, "sha512", 64,
51785732ac8SCy Schubert 							   &pos,
51885732ac8SCy Schubert 							   line, fname) < 0)
51985732ac8SCy Schubert 				goto failed;
520e28a4053SRui Paulo 		} else {
521e28a4053SRui Paulo 			pos2 = pos;
522e28a4053SRui Paulo 			while (*pos2 != '\0' && *pos2 != ' ' &&
523e28a4053SRui Paulo 			       *pos2 != '\t' && *pos2 != '#')
524e28a4053SRui Paulo 				pos2++;
525e28a4053SRui Paulo 			if ((pos2 - pos) & 1) {
526e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid hex password "
527e28a4053SRui Paulo 					   "on line %d in '%s'", line, fname);
528e28a4053SRui Paulo 				goto failed;
529e28a4053SRui Paulo 			}
530e28a4053SRui Paulo 			user->password = os_malloc((pos2 - pos) / 2);
531e28a4053SRui Paulo 			if (user->password == NULL) {
532e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Failed to allocate "
533e28a4053SRui Paulo 					   "memory for EAP password");
534e28a4053SRui Paulo 				goto failed;
535e28a4053SRui Paulo 			}
536e28a4053SRui Paulo 			if (hexstr2bin(pos, user->password,
537e28a4053SRui Paulo 				       (pos2 - pos) / 2) < 0) {
538e28a4053SRui Paulo 				wpa_printf(MSG_ERROR, "Invalid hex password "
539e28a4053SRui Paulo 					   "on line %d in '%s'", line, fname);
540e28a4053SRui Paulo 				goto failed;
541e28a4053SRui Paulo 			}
542e28a4053SRui Paulo 			user->password_len = (pos2 - pos) / 2;
543e28a4053SRui Paulo 			pos = pos2;
544e28a4053SRui Paulo 		}
545e28a4053SRui Paulo 
546e28a4053SRui Paulo 		while (*pos == ' ' || *pos == '\t')
547e28a4053SRui Paulo 			pos++;
548e28a4053SRui Paulo 		if (os_strncmp(pos, "[2]", 3) == 0) {
549e28a4053SRui Paulo 			user->phase2 = 1;
550e28a4053SRui Paulo 		}
551e28a4053SRui Paulo 
552e28a4053SRui Paulo 	done:
553e28a4053SRui Paulo 		if (tail == NULL) {
5545b9c547cSRui Paulo 			tail = new_user = user;
555e28a4053SRui Paulo 		} else {
556e28a4053SRui Paulo 			tail->next = user;
557e28a4053SRui Paulo 			tail = user;
558e28a4053SRui Paulo 		}
559e28a4053SRui Paulo 		continue;
560e28a4053SRui Paulo 
561e28a4053SRui Paulo 	failed:
5625b9c547cSRui Paulo 		if (user)
5635b9c547cSRui Paulo 			hostapd_config_free_eap_user(user);
564e28a4053SRui Paulo 		ret = -1;
565e28a4053SRui Paulo 		break;
566e28a4053SRui Paulo 	}
567e28a4053SRui Paulo 
568e28a4053SRui Paulo 	fclose(f);
569e28a4053SRui Paulo 
5705b9c547cSRui Paulo 	if (ret == 0) {
57185732ac8SCy Schubert 		hostapd_config_free_eap_users(conf->eap_user);
5725b9c547cSRui Paulo 		conf->eap_user = new_user;
57385732ac8SCy Schubert 	} else {
57485732ac8SCy Schubert 		hostapd_config_free_eap_users(new_user);
5755b9c547cSRui Paulo 	}
5765b9c547cSRui Paulo 
577e28a4053SRui Paulo 	return ret;
578e28a4053SRui Paulo }
57985732ac8SCy Schubert 
580e28a4053SRui Paulo #endif /* EAP_SERVER */
581e28a4053SRui Paulo 
582e28a4053SRui Paulo 
583e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS
584e28a4053SRui Paulo static int
hostapd_config_read_radius_addr(struct hostapd_radius_server ** server,int * num_server,const char * val,int def_port,struct hostapd_radius_server ** curr_serv)585e28a4053SRui Paulo hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
586e28a4053SRui Paulo 				int *num_server, const char *val, int def_port,
587e28a4053SRui Paulo 				struct hostapd_radius_server **curr_serv)
588e28a4053SRui Paulo {
589e28a4053SRui Paulo 	struct hostapd_radius_server *nserv;
590e28a4053SRui Paulo 	int ret;
591e28a4053SRui Paulo 	static int server_index = 1;
592e28a4053SRui Paulo 
593f05cddf9SRui Paulo 	nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv));
594e28a4053SRui Paulo 	if (nserv == NULL)
595e28a4053SRui Paulo 		return -1;
596e28a4053SRui Paulo 
597e28a4053SRui Paulo 	*server = nserv;
598e28a4053SRui Paulo 	nserv = &nserv[*num_server];
599e28a4053SRui Paulo 	(*num_server)++;
600e28a4053SRui Paulo 	(*curr_serv) = nserv;
601e28a4053SRui Paulo 
602e28a4053SRui Paulo 	os_memset(nserv, 0, sizeof(*nserv));
603e28a4053SRui Paulo 	nserv->port = def_port;
604e28a4053SRui Paulo 	ret = hostapd_parse_ip_addr(val, &nserv->addr);
605e28a4053SRui Paulo 	nserv->index = server_index++;
606e28a4053SRui Paulo 
607e28a4053SRui Paulo 	return ret;
608e28a4053SRui Paulo }
609f05cddf9SRui Paulo 
610f05cddf9SRui Paulo 
611f05cddf9SRui Paulo 
hostapd_parse_das_client(struct hostapd_bss_config * bss,char * val)612780fb4a2SCy Schubert static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
613f05cddf9SRui Paulo {
614f05cddf9SRui Paulo 	char *secret;
615f05cddf9SRui Paulo 
616f05cddf9SRui Paulo 	secret = os_strchr(val, ' ');
617f05cddf9SRui Paulo 	if (secret == NULL)
618f05cddf9SRui Paulo 		return -1;
619f05cddf9SRui Paulo 
620780fb4a2SCy Schubert 	*secret++ = '\0';
621f05cddf9SRui Paulo 
622f05cddf9SRui Paulo 	if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
623f05cddf9SRui Paulo 		return -1;
624f05cddf9SRui Paulo 
625f05cddf9SRui Paulo 	os_free(bss->radius_das_shared_secret);
626f05cddf9SRui Paulo 	bss->radius_das_shared_secret = (u8 *) os_strdup(secret);
627f05cddf9SRui Paulo 	if (bss->radius_das_shared_secret == NULL)
628f05cddf9SRui Paulo 		return -1;
629f05cddf9SRui Paulo 	bss->radius_das_shared_secret_len = os_strlen(secret);
630f05cddf9SRui Paulo 
631f05cddf9SRui Paulo 	return 0;
632f05cddf9SRui Paulo }
633e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */
634e28a4053SRui Paulo 
635e28a4053SRui Paulo 
hostapd_config_parse_key_mgmt(int line,const char * value)636e28a4053SRui Paulo static int hostapd_config_parse_key_mgmt(int line, const char *value)
637e28a4053SRui Paulo {
638e28a4053SRui Paulo 	int val = 0, last;
639e28a4053SRui Paulo 	char *start, *end, *buf;
640e28a4053SRui Paulo 
641e28a4053SRui Paulo 	buf = os_strdup(value);
642e28a4053SRui Paulo 	if (buf == NULL)
643e28a4053SRui Paulo 		return -1;
644e28a4053SRui Paulo 	start = buf;
645e28a4053SRui Paulo 
646e28a4053SRui Paulo 	while (*start != '\0') {
647e28a4053SRui Paulo 		while (*start == ' ' || *start == '\t')
648e28a4053SRui Paulo 			start++;
649e28a4053SRui Paulo 		if (*start == '\0')
650e28a4053SRui Paulo 			break;
651e28a4053SRui Paulo 		end = start;
652e28a4053SRui Paulo 		while (*end != ' ' && *end != '\t' && *end != '\0')
653e28a4053SRui Paulo 			end++;
654e28a4053SRui Paulo 		last = *end == '\0';
655e28a4053SRui Paulo 		*end = '\0';
656e28a4053SRui Paulo 		if (os_strcmp(start, "WPA-PSK") == 0)
657e28a4053SRui Paulo 			val |= WPA_KEY_MGMT_PSK;
658e28a4053SRui Paulo 		else if (os_strcmp(start, "WPA-EAP") == 0)
659e28a4053SRui Paulo 			val |= WPA_KEY_MGMT_IEEE8021X;
66085732ac8SCy Schubert #ifdef CONFIG_IEEE80211R_AP
661e28a4053SRui Paulo 		else if (os_strcmp(start, "FT-PSK") == 0)
662e28a4053SRui Paulo 			val |= WPA_KEY_MGMT_FT_PSK;
663e28a4053SRui Paulo 		else if (os_strcmp(start, "FT-EAP") == 0)
664e28a4053SRui Paulo 			val |= WPA_KEY_MGMT_FT_IEEE8021X;
66585732ac8SCy Schubert #ifdef CONFIG_SHA384
66685732ac8SCy Schubert 		else if (os_strcmp(start, "FT-EAP-SHA384") == 0)
66785732ac8SCy Schubert 			val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
66885732ac8SCy Schubert #endif /* CONFIG_SHA384 */
66985732ac8SCy Schubert #endif /* CONFIG_IEEE80211R_AP */
670*a90b9d01SCy Schubert #ifdef CONFIG_SHA384
671*a90b9d01SCy Schubert 		else if (os_strcmp(start, "WPA-EAP-SHA384") == 0)
672*a90b9d01SCy Schubert 			val |= WPA_KEY_MGMT_IEEE8021X_SHA384;
673*a90b9d01SCy Schubert #endif /* CONFIG_SHA384 */
674e28a4053SRui Paulo 		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
675e28a4053SRui Paulo 			val |= WPA_KEY_MGMT_PSK_SHA256;
676e28a4053SRui Paulo 		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
677e28a4053SRui Paulo 			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
678f05cddf9SRui Paulo #ifdef CONFIG_SAE
679f05cddf9SRui Paulo 		else if (os_strcmp(start, "SAE") == 0)
680f05cddf9SRui Paulo 			val |= WPA_KEY_MGMT_SAE;
681*a90b9d01SCy Schubert 		else if (os_strcmp(start, "SAE-EXT-KEY") == 0)
682*a90b9d01SCy Schubert 			val |= WPA_KEY_MGMT_SAE_EXT_KEY;
683f05cddf9SRui Paulo 		else if (os_strcmp(start, "FT-SAE") == 0)
684f05cddf9SRui Paulo 			val |= WPA_KEY_MGMT_FT_SAE;
685*a90b9d01SCy Schubert 		else if (os_strcmp(start, "FT-SAE-EXT-KEY") == 0)
686*a90b9d01SCy Schubert 			val |= WPA_KEY_MGMT_FT_SAE_EXT_KEY;
687f05cddf9SRui Paulo #endif /* CONFIG_SAE */
6885b9c547cSRui Paulo #ifdef CONFIG_SUITEB
6895b9c547cSRui Paulo 		else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
6905b9c547cSRui Paulo 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
6915b9c547cSRui Paulo #endif /* CONFIG_SUITEB */
6925b9c547cSRui Paulo #ifdef CONFIG_SUITEB192
6935b9c547cSRui Paulo 		else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
6945b9c547cSRui Paulo 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
6955b9c547cSRui Paulo #endif /* CONFIG_SUITEB192 */
69685732ac8SCy Schubert #ifdef CONFIG_FILS
69785732ac8SCy Schubert 		else if (os_strcmp(start, "FILS-SHA256") == 0)
69885732ac8SCy Schubert 			val |= WPA_KEY_MGMT_FILS_SHA256;
69985732ac8SCy Schubert 		else if (os_strcmp(start, "FILS-SHA384") == 0)
70085732ac8SCy Schubert 			val |= WPA_KEY_MGMT_FILS_SHA384;
70185732ac8SCy Schubert #ifdef CONFIG_IEEE80211R_AP
70285732ac8SCy Schubert 		else if (os_strcmp(start, "FT-FILS-SHA256") == 0)
70385732ac8SCy Schubert 			val |= WPA_KEY_MGMT_FT_FILS_SHA256;
70485732ac8SCy Schubert 		else if (os_strcmp(start, "FT-FILS-SHA384") == 0)
70585732ac8SCy Schubert 			val |= WPA_KEY_MGMT_FT_FILS_SHA384;
70685732ac8SCy Schubert #endif /* CONFIG_IEEE80211R_AP */
70785732ac8SCy Schubert #endif /* CONFIG_FILS */
70885732ac8SCy Schubert #ifdef CONFIG_OWE
70985732ac8SCy Schubert 		else if (os_strcmp(start, "OWE") == 0)
71085732ac8SCy Schubert 			val |= WPA_KEY_MGMT_OWE;
71185732ac8SCy Schubert #endif /* CONFIG_OWE */
71285732ac8SCy Schubert #ifdef CONFIG_DPP
71385732ac8SCy Schubert 		else if (os_strcmp(start, "DPP") == 0)
71485732ac8SCy Schubert 			val |= WPA_KEY_MGMT_DPP;
71585732ac8SCy Schubert #endif /* CONFIG_DPP */
71685732ac8SCy Schubert #ifdef CONFIG_HS20
71785732ac8SCy Schubert 		else if (os_strcmp(start, "OSEN") == 0)
71885732ac8SCy Schubert 			val |= WPA_KEY_MGMT_OSEN;
71985732ac8SCy Schubert #endif /* CONFIG_HS20 */
720c1d255d3SCy Schubert #ifdef CONFIG_PASN
721c1d255d3SCy Schubert 		else if (os_strcmp(start, "PASN") == 0)
722c1d255d3SCy Schubert 			val |= WPA_KEY_MGMT_PASN;
723c1d255d3SCy Schubert #endif /* CONFIG_PASN */
724e28a4053SRui Paulo 		else {
725e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
726e28a4053SRui Paulo 				   line, start);
727e28a4053SRui Paulo 			os_free(buf);
728e28a4053SRui Paulo 			return -1;
729e28a4053SRui Paulo 		}
730e28a4053SRui Paulo 
731e28a4053SRui Paulo 		if (last)
732e28a4053SRui Paulo 			break;
733e28a4053SRui Paulo 		start = end + 1;
734e28a4053SRui Paulo 	}
735e28a4053SRui Paulo 
736e28a4053SRui Paulo 	os_free(buf);
737e28a4053SRui Paulo 	if (val == 0) {
738e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values "
739e28a4053SRui Paulo 			   "configured.", line);
740e28a4053SRui Paulo 		return -1;
741e28a4053SRui Paulo 	}
742e28a4053SRui Paulo 
743e28a4053SRui Paulo 	return val;
744e28a4053SRui Paulo }
745e28a4053SRui Paulo 
746e28a4053SRui Paulo 
hostapd_config_parse_cipher(int line,const char * value)747e28a4053SRui Paulo static int hostapd_config_parse_cipher(int line, const char *value)
748e28a4053SRui Paulo {
7495b9c547cSRui Paulo 	int val = wpa_parse_cipher(value);
7505b9c547cSRui Paulo 	if (val < 0) {
751e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
7525b9c547cSRui Paulo 			   line, value);
753e28a4053SRui Paulo 		return -1;
754e28a4053SRui Paulo 	}
755e28a4053SRui Paulo 	if (val == 0) {
756e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
757e28a4053SRui Paulo 			   line);
758e28a4053SRui Paulo 		return -1;
759e28a4053SRui Paulo 	}
760e28a4053SRui Paulo 	return val;
761e28a4053SRui Paulo }
762e28a4053SRui Paulo 
763e28a4053SRui Paulo 
764c1d255d3SCy Schubert #ifdef CONFIG_WEP
hostapd_config_read_wep(struct hostapd_wep_keys * wep,int keyidx,char * val)765e28a4053SRui Paulo static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
766e28a4053SRui Paulo 				   char *val)
767e28a4053SRui Paulo {
768e28a4053SRui Paulo 	size_t len = os_strlen(val);
769e28a4053SRui Paulo 
77085732ac8SCy Schubert 	if (keyidx < 0 || keyidx > 3)
77185732ac8SCy Schubert 		return -1;
77285732ac8SCy Schubert 
77385732ac8SCy Schubert 	if (len == 0) {
77485732ac8SCy Schubert 		int i, set = 0;
77585732ac8SCy Schubert 
77685732ac8SCy Schubert 		bin_clear_free(wep->key[keyidx], wep->len[keyidx]);
77785732ac8SCy Schubert 		wep->key[keyidx] = NULL;
77885732ac8SCy Schubert 		wep->len[keyidx] = 0;
77985732ac8SCy Schubert 		for (i = 0; i < NUM_WEP_KEYS; i++) {
78085732ac8SCy Schubert 			if (wep->key[i])
78185732ac8SCy Schubert 				set++;
78285732ac8SCy Schubert 		}
78385732ac8SCy Schubert 		if (!set)
78485732ac8SCy Schubert 			wep->keys_set = 0;
78585732ac8SCy Schubert 		return 0;
78685732ac8SCy Schubert 	}
78785732ac8SCy Schubert 
78885732ac8SCy Schubert 	if (wep->key[keyidx] != NULL)
789e28a4053SRui Paulo 		return -1;
790e28a4053SRui Paulo 
791e28a4053SRui Paulo 	if (val[0] == '"') {
792e28a4053SRui Paulo 		if (len < 2 || val[len - 1] != '"')
793e28a4053SRui Paulo 			return -1;
794e28a4053SRui Paulo 		len -= 2;
79585732ac8SCy Schubert 		wep->key[keyidx] = os_memdup(val + 1, len);
796e28a4053SRui Paulo 		if (wep->key[keyidx] == NULL)
797e28a4053SRui Paulo 			return -1;
798e28a4053SRui Paulo 		wep->len[keyidx] = len;
799e28a4053SRui Paulo 	} else {
800e28a4053SRui Paulo 		if (len & 1)
801e28a4053SRui Paulo 			return -1;
802e28a4053SRui Paulo 		len /= 2;
803e28a4053SRui Paulo 		wep->key[keyidx] = os_malloc(len);
804e28a4053SRui Paulo 		if (wep->key[keyidx] == NULL)
805e28a4053SRui Paulo 			return -1;
806e28a4053SRui Paulo 		wep->len[keyidx] = len;
807e28a4053SRui Paulo 		if (hexstr2bin(val, wep->key[keyidx], len) < 0)
808e28a4053SRui Paulo 			return -1;
809e28a4053SRui Paulo 	}
810e28a4053SRui Paulo 
811e28a4053SRui Paulo 	wep->keys_set++;
812e28a4053SRui Paulo 
813e28a4053SRui Paulo 	return 0;
814e28a4053SRui Paulo }
815c1d255d3SCy Schubert #endif /* CONFIG_WEP */
816e28a4053SRui Paulo 
817e28a4053SRui Paulo 
hostapd_parse_chanlist(struct hostapd_config * conf,char * val)818325151a3SRui Paulo static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
819325151a3SRui Paulo {
820325151a3SRui Paulo 	char *pos;
821325151a3SRui Paulo 
822325151a3SRui Paulo 	/* for backwards compatibility, translate ' ' in conf str to ',' */
823325151a3SRui Paulo 	pos = val;
824325151a3SRui Paulo 	while (pos) {
825325151a3SRui Paulo 		pos = os_strchr(pos, ' ');
826325151a3SRui Paulo 		if (pos)
827325151a3SRui Paulo 			*pos++ = ',';
828325151a3SRui Paulo 	}
829325151a3SRui Paulo 	if (freq_range_list_parse(&conf->acs_ch_list, val))
830325151a3SRui Paulo 		return -1;
831325151a3SRui Paulo 
832325151a3SRui Paulo 	return 0;
833325151a3SRui Paulo }
834325151a3SRui Paulo 
835325151a3SRui Paulo 
hostapd_parse_intlist(int ** int_list,char * val)8365b9c547cSRui Paulo static int hostapd_parse_intlist(int **int_list, char *val)
837e28a4053SRui Paulo {
838e28a4053SRui Paulo 	int *list;
839e28a4053SRui Paulo 	int count;
840e28a4053SRui Paulo 	char *pos, *end;
841e28a4053SRui Paulo 
8425b9c547cSRui Paulo 	os_free(*int_list);
8435b9c547cSRui Paulo 	*int_list = NULL;
844e28a4053SRui Paulo 
845e28a4053SRui Paulo 	pos = val;
846e28a4053SRui Paulo 	count = 0;
847e28a4053SRui Paulo 	while (*pos != '\0') {
848e28a4053SRui Paulo 		if (*pos == ' ')
849e28a4053SRui Paulo 			count++;
850e28a4053SRui Paulo 		pos++;
851e28a4053SRui Paulo 	}
852e28a4053SRui Paulo 
853e28a4053SRui Paulo 	list = os_malloc(sizeof(int) * (count + 2));
854e28a4053SRui Paulo 	if (list == NULL)
855e28a4053SRui Paulo 		return -1;
856e28a4053SRui Paulo 	pos = val;
857e28a4053SRui Paulo 	count = 0;
858e28a4053SRui Paulo 	while (*pos != '\0') {
859e28a4053SRui Paulo 		end = os_strchr(pos, ' ');
860e28a4053SRui Paulo 		if (end)
861e28a4053SRui Paulo 			*end = '\0';
862e28a4053SRui Paulo 
863e28a4053SRui Paulo 		list[count++] = atoi(pos);
864e28a4053SRui Paulo 		if (!end)
865e28a4053SRui Paulo 			break;
866e28a4053SRui Paulo 		pos = end + 1;
867e28a4053SRui Paulo 	}
868e28a4053SRui Paulo 	list[count] = -1;
869e28a4053SRui Paulo 
8705b9c547cSRui Paulo 	*int_list = list;
871e28a4053SRui Paulo 	return 0;
872e28a4053SRui Paulo }
873e28a4053SRui Paulo 
874e28a4053SRui Paulo 
hostapd_config_bss(struct hostapd_config * conf,const char * ifname)875e28a4053SRui Paulo static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
876e28a4053SRui Paulo {
8775b9c547cSRui Paulo 	struct hostapd_bss_config **all, *bss;
878e28a4053SRui Paulo 
879e28a4053SRui Paulo 	if (*ifname == '\0')
880e28a4053SRui Paulo 		return -1;
881e28a4053SRui Paulo 
8825b9c547cSRui Paulo 	all = os_realloc_array(conf->bss, conf->num_bss + 1,
8835b9c547cSRui Paulo 			       sizeof(struct hostapd_bss_config *));
8845b9c547cSRui Paulo 	if (all == NULL) {
885e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
886e28a4053SRui Paulo 			   "multi-BSS entry");
887e28a4053SRui Paulo 		return -1;
888e28a4053SRui Paulo 	}
8895b9c547cSRui Paulo 	conf->bss = all;
890e28a4053SRui Paulo 
8915b9c547cSRui Paulo 	bss = os_zalloc(sizeof(*bss));
8925b9c547cSRui Paulo 	if (bss == NULL)
8935b9c547cSRui Paulo 		return -1;
894e28a4053SRui Paulo 	bss->radius = os_zalloc(sizeof(*bss->radius));
895e28a4053SRui Paulo 	if (bss->radius == NULL) {
896e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
897e28a4053SRui Paulo 			   "multi-BSS RADIUS data");
8985b9c547cSRui Paulo 		os_free(bss);
899e28a4053SRui Paulo 		return -1;
900e28a4053SRui Paulo 	}
901e28a4053SRui Paulo 
9025b9c547cSRui Paulo 	conf->bss[conf->num_bss++] = bss;
903e28a4053SRui Paulo 	conf->last_bss = bss;
904e28a4053SRui Paulo 
905e28a4053SRui Paulo 	hostapd_config_defaults_bss(bss);
906e28a4053SRui Paulo 	os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
907e28a4053SRui Paulo 	os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
908e28a4053SRui Paulo 
909e28a4053SRui Paulo 	return 0;
910e28a4053SRui Paulo }
911e28a4053SRui Paulo 
912e28a4053SRui Paulo 
91385732ac8SCy Schubert #ifdef CONFIG_IEEE80211R_AP
91485732ac8SCy Schubert 
rkh_derive_key(const char * pos,u8 * key,size_t key_len)91585732ac8SCy Schubert static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
91685732ac8SCy Schubert {
91785732ac8SCy Schubert 	u8 oldkey[16];
91885732ac8SCy Schubert 	int ret;
91985732ac8SCy Schubert 
92085732ac8SCy Schubert 	if (!hexstr2bin(pos, key, key_len))
92185732ac8SCy Schubert 		return 0;
92285732ac8SCy Schubert 
92385732ac8SCy Schubert 	/* Try to use old short key for backwards compatibility */
92485732ac8SCy Schubert 	if (hexstr2bin(pos, oldkey, sizeof(oldkey)))
92585732ac8SCy Schubert 		return -1;
92685732ac8SCy Schubert 
92785732ac8SCy Schubert 	ret = hmac_sha256_kdf(oldkey, sizeof(oldkey), "FT OLDKEY", NULL, 0,
92885732ac8SCy Schubert 			      key, key_len);
92985732ac8SCy Schubert 	os_memset(oldkey, 0, sizeof(oldkey));
93085732ac8SCy Schubert 	return ret;
93185732ac8SCy Schubert }
93285732ac8SCy Schubert 
93385732ac8SCy Schubert 
add_r0kh(struct hostapd_bss_config * bss,char * value)934e28a4053SRui Paulo static int add_r0kh(struct hostapd_bss_config *bss, char *value)
935e28a4053SRui Paulo {
936e28a4053SRui Paulo 	struct ft_remote_r0kh *r0kh;
937e28a4053SRui Paulo 	char *pos, *next;
938e28a4053SRui Paulo 
939e28a4053SRui Paulo 	r0kh = os_zalloc(sizeof(*r0kh));
940e28a4053SRui Paulo 	if (r0kh == NULL)
941e28a4053SRui Paulo 		return -1;
942e28a4053SRui Paulo 
943e28a4053SRui Paulo 	/* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
944e28a4053SRui Paulo 	pos = value;
945e28a4053SRui Paulo 	next = os_strchr(pos, ' ');
946e28a4053SRui Paulo 	if (next)
947e28a4053SRui Paulo 		*next++ = '\0';
948e28a4053SRui Paulo 	if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
949e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos);
950e28a4053SRui Paulo 		os_free(r0kh);
951e28a4053SRui Paulo 		return -1;
952e28a4053SRui Paulo 	}
953e28a4053SRui Paulo 
954e28a4053SRui Paulo 	pos = next;
955e28a4053SRui Paulo 	next = os_strchr(pos, ' ');
956e28a4053SRui Paulo 	if (next)
957e28a4053SRui Paulo 		*next++ = '\0';
958e28a4053SRui Paulo 	if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
959e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos);
960e28a4053SRui Paulo 		os_free(r0kh);
961e28a4053SRui Paulo 		return -1;
962e28a4053SRui Paulo 	}
963e28a4053SRui Paulo 	r0kh->id_len = next - pos - 1;
964e28a4053SRui Paulo 	os_memcpy(r0kh->id, pos, r0kh->id_len);
965e28a4053SRui Paulo 
966e28a4053SRui Paulo 	pos = next;
96785732ac8SCy Schubert 	if (rkh_derive_key(pos, r0kh->key, sizeof(r0kh->key)) < 0) {
968e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos);
969e28a4053SRui Paulo 		os_free(r0kh);
970e28a4053SRui Paulo 		return -1;
971e28a4053SRui Paulo 	}
972e28a4053SRui Paulo 
973e28a4053SRui Paulo 	r0kh->next = bss->r0kh_list;
974e28a4053SRui Paulo 	bss->r0kh_list = r0kh;
975e28a4053SRui Paulo 
976e28a4053SRui Paulo 	return 0;
977e28a4053SRui Paulo }
978e28a4053SRui Paulo 
979e28a4053SRui Paulo 
add_r1kh(struct hostapd_bss_config * bss,char * value)980e28a4053SRui Paulo static int add_r1kh(struct hostapd_bss_config *bss, char *value)
981e28a4053SRui Paulo {
982e28a4053SRui Paulo 	struct ft_remote_r1kh *r1kh;
983e28a4053SRui Paulo 	char *pos, *next;
984e28a4053SRui Paulo 
985e28a4053SRui Paulo 	r1kh = os_zalloc(sizeof(*r1kh));
986e28a4053SRui Paulo 	if (r1kh == NULL)
987e28a4053SRui Paulo 		return -1;
988e28a4053SRui Paulo 
989e28a4053SRui Paulo 	/* 02:01:02:03:04:05 02:01:02:03:04:05
990e28a4053SRui Paulo 	 * 000102030405060708090a0b0c0d0e0f */
991e28a4053SRui Paulo 	pos = value;
992e28a4053SRui Paulo 	next = os_strchr(pos, ' ');
993e28a4053SRui Paulo 	if (next)
994e28a4053SRui Paulo 		*next++ = '\0';
995e28a4053SRui Paulo 	if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
996e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos);
997e28a4053SRui Paulo 		os_free(r1kh);
998e28a4053SRui Paulo 		return -1;
999e28a4053SRui Paulo 	}
1000e28a4053SRui Paulo 
1001e28a4053SRui Paulo 	pos = next;
1002e28a4053SRui Paulo 	next = os_strchr(pos, ' ');
1003e28a4053SRui Paulo 	if (next)
1004e28a4053SRui Paulo 		*next++ = '\0';
1005e28a4053SRui Paulo 	if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
1006e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos);
1007e28a4053SRui Paulo 		os_free(r1kh);
1008e28a4053SRui Paulo 		return -1;
1009e28a4053SRui Paulo 	}
1010e28a4053SRui Paulo 
1011e28a4053SRui Paulo 	pos = next;
101285732ac8SCy Schubert 	if (rkh_derive_key(pos, r1kh->key, sizeof(r1kh->key)) < 0) {
1013e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos);
1014e28a4053SRui Paulo 		os_free(r1kh);
1015e28a4053SRui Paulo 		return -1;
1016e28a4053SRui Paulo 	}
1017e28a4053SRui Paulo 
1018e28a4053SRui Paulo 	r1kh->next = bss->r1kh_list;
1019e28a4053SRui Paulo 	bss->r1kh_list = r1kh;
1020e28a4053SRui Paulo 
1021e28a4053SRui Paulo 	return 0;
1022e28a4053SRui Paulo }
1023*a90b9d01SCy Schubert 
1024*a90b9d01SCy Schubert 
hostapd_config_read_rxkh_file(struct hostapd_bss_config * conf,const char * fname)1025*a90b9d01SCy Schubert int hostapd_config_read_rxkh_file(struct hostapd_bss_config *conf,
1026*a90b9d01SCy Schubert 				  const char *fname)
1027*a90b9d01SCy Schubert {
1028*a90b9d01SCy Schubert 	FILE *f;
1029*a90b9d01SCy Schubert 	char buf[256], *pos;
1030*a90b9d01SCy Schubert 	int line = 0, errors = 0;
1031*a90b9d01SCy Schubert 
1032*a90b9d01SCy Schubert 	if (!fname)
1033*a90b9d01SCy Schubert 		return 0;
1034*a90b9d01SCy Schubert 
1035*a90b9d01SCy Schubert 	f = fopen(fname, "r");
1036*a90b9d01SCy Schubert 	if (!f) {
1037*a90b9d01SCy Schubert 		wpa_printf(MSG_ERROR, "rxkh file '%s' not found.", fname);
1038*a90b9d01SCy Schubert 		return -1;
1039*a90b9d01SCy Schubert 	}
1040*a90b9d01SCy Schubert 
1041*a90b9d01SCy Schubert 	while (fgets(buf, sizeof(buf), f)) {
1042*a90b9d01SCy Schubert 		line++;
1043*a90b9d01SCy Schubert 
1044*a90b9d01SCy Schubert 		if (buf[0] == '#')
1045*a90b9d01SCy Schubert 			continue;
1046*a90b9d01SCy Schubert 		pos = buf;
1047*a90b9d01SCy Schubert 		while (*pos != '\0') {
1048*a90b9d01SCy Schubert 			if (*pos == '\n') {
1049*a90b9d01SCy Schubert 				*pos = '\0';
1050*a90b9d01SCy Schubert 				break;
1051*a90b9d01SCy Schubert 			}
1052*a90b9d01SCy Schubert 			pos++;
1053*a90b9d01SCy Schubert 		}
1054*a90b9d01SCy Schubert 		if (buf[0] == '\0')
1055*a90b9d01SCy Schubert 			continue;
1056*a90b9d01SCy Schubert 
1057*a90b9d01SCy Schubert 		pos = os_strchr(buf, '=');
1058*a90b9d01SCy Schubert 		if (!pos) {
1059*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid line '%s'",
1060*a90b9d01SCy Schubert 				   line, buf);
1061*a90b9d01SCy Schubert 			errors++;
1062*a90b9d01SCy Schubert 			continue;
1063*a90b9d01SCy Schubert 		}
1064*a90b9d01SCy Schubert 		*pos = '\0';
1065*a90b9d01SCy Schubert 		pos++;
1066*a90b9d01SCy Schubert 
1067*a90b9d01SCy Schubert 		if (os_strcmp(buf, "r0kh") == 0) {
1068*a90b9d01SCy Schubert 			if (add_r0kh(conf, pos) < 0) {
1069*a90b9d01SCy Schubert 				wpa_printf(MSG_ERROR,
1070*a90b9d01SCy Schubert 					   "Line %d: Invalid r0kh '%s'",
1071*a90b9d01SCy Schubert 					   line, pos);
1072*a90b9d01SCy Schubert 				errors++;
1073*a90b9d01SCy Schubert 			}
1074*a90b9d01SCy Schubert 		} else if (os_strcmp(buf, "r1kh") == 0) {
1075*a90b9d01SCy Schubert 			if (add_r1kh(conf, pos) < 0) {
1076*a90b9d01SCy Schubert 				wpa_printf(MSG_ERROR,
1077*a90b9d01SCy Schubert 					   "Line %d: Invalid r1kh '%s'",
1078*a90b9d01SCy Schubert 					   line, pos);
1079*a90b9d01SCy Schubert 				errors++;
1080*a90b9d01SCy Schubert 			}
1081*a90b9d01SCy Schubert 		}
1082*a90b9d01SCy Schubert 	}
1083*a90b9d01SCy Schubert 
1084*a90b9d01SCy Schubert 	fclose(f);
1085*a90b9d01SCy Schubert 
1086*a90b9d01SCy Schubert 	if (errors) {
1087*a90b9d01SCy Schubert 		wpa_printf(MSG_ERROR,
1088*a90b9d01SCy Schubert 			   "%d errors in configuring RxKHs from '%s'",
1089*a90b9d01SCy Schubert 			   errors, fname);
1090*a90b9d01SCy Schubert 		return -1;
1091*a90b9d01SCy Schubert 	}
1092*a90b9d01SCy Schubert 	return 0;
1093*a90b9d01SCy Schubert }
1094*a90b9d01SCy Schubert 
109585732ac8SCy Schubert #endif /* CONFIG_IEEE80211R_AP */
1096e28a4053SRui Paulo 
1097e28a4053SRui Paulo 
hostapd_config_ht_capab(struct hostapd_config * conf,const char * capab)1098e28a4053SRui Paulo static int hostapd_config_ht_capab(struct hostapd_config *conf,
1099e28a4053SRui Paulo 				   const char *capab)
1100e28a4053SRui Paulo {
1101e28a4053SRui Paulo 	if (os_strstr(capab, "[LDPC]"))
1102e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
1103e28a4053SRui Paulo 	if (os_strstr(capab, "[HT40-]")) {
1104e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1105e28a4053SRui Paulo 		conf->secondary_channel = -1;
1106e28a4053SRui Paulo 	}
1107e28a4053SRui Paulo 	if (os_strstr(capab, "[HT40+]")) {
1108e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1109e28a4053SRui Paulo 		conf->secondary_channel = 1;
1110e28a4053SRui Paulo 	}
111185732ac8SCy Schubert 	if (os_strstr(capab, "[HT40+]") && os_strstr(capab, "[HT40-]")) {
111285732ac8SCy Schubert 		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
111385732ac8SCy Schubert 		conf->ht40_plus_minus_allowed = 1;
111485732ac8SCy Schubert 	}
111585732ac8SCy Schubert 	if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
111685732ac8SCy Schubert 		conf->secondary_channel = 0;
1117e28a4053SRui Paulo 	if (os_strstr(capab, "[GF]"))
1118e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
1119e28a4053SRui Paulo 	if (os_strstr(capab, "[SHORT-GI-20]"))
1120e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
1121e28a4053SRui Paulo 	if (os_strstr(capab, "[SHORT-GI-40]"))
1122e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
1123e28a4053SRui Paulo 	if (os_strstr(capab, "[TX-STBC]"))
1124e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_TX_STBC;
1125e28a4053SRui Paulo 	if (os_strstr(capab, "[RX-STBC1]")) {
1126e28a4053SRui Paulo 		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1127e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_RX_STBC_1;
1128e28a4053SRui Paulo 	}
1129e28a4053SRui Paulo 	if (os_strstr(capab, "[RX-STBC12]")) {
1130e28a4053SRui Paulo 		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1131e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_RX_STBC_12;
1132e28a4053SRui Paulo 	}
1133e28a4053SRui Paulo 	if (os_strstr(capab, "[RX-STBC123]")) {
1134e28a4053SRui Paulo 		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1135e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_RX_STBC_123;
1136e28a4053SRui Paulo 	}
1137e28a4053SRui Paulo 	if (os_strstr(capab, "[DELAYED-BA]"))
1138e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
1139e28a4053SRui Paulo 	if (os_strstr(capab, "[MAX-AMSDU-7935]"))
1140e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
1141e28a4053SRui Paulo 	if (os_strstr(capab, "[DSSS_CCK-40]"))
1142e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
11435b9c547cSRui Paulo 	if (os_strstr(capab, "[40-INTOLERANT]"))
11445b9c547cSRui Paulo 		conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
1145e28a4053SRui Paulo 	if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
1146e28a4053SRui Paulo 		conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
1147e28a4053SRui Paulo 
1148e28a4053SRui Paulo 	return 0;
1149e28a4053SRui Paulo }
1150e28a4053SRui Paulo 
1151e28a4053SRui Paulo 
1152f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211AC
hostapd_config_vht_capab(struct hostapd_config * conf,const char * capab)1153f05cddf9SRui Paulo static int hostapd_config_vht_capab(struct hostapd_config *conf,
1154f05cddf9SRui Paulo 				    const char *capab)
1155f05cddf9SRui Paulo {
1156f05cddf9SRui Paulo 	if (os_strstr(capab, "[MAX-MPDU-7991]"))
1157f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
1158f05cddf9SRui Paulo 	if (os_strstr(capab, "[MAX-MPDU-11454]"))
1159f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
1160f05cddf9SRui Paulo 	if (os_strstr(capab, "[VHT160]"))
1161f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1162f05cddf9SRui Paulo 	if (os_strstr(capab, "[VHT160-80PLUS80]"))
1163f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1164f05cddf9SRui Paulo 	if (os_strstr(capab, "[RXLDPC]"))
1165f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_RXLDPC;
1166f05cddf9SRui Paulo 	if (os_strstr(capab, "[SHORT-GI-80]"))
1167f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_SHORT_GI_80;
1168f05cddf9SRui Paulo 	if (os_strstr(capab, "[SHORT-GI-160]"))
1169f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_SHORT_GI_160;
1170f05cddf9SRui Paulo 	if (os_strstr(capab, "[TX-STBC-2BY1]"))
1171f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_TXSTBC;
1172f05cddf9SRui Paulo 	if (os_strstr(capab, "[RX-STBC-1]"))
1173f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_RXSTBC_1;
1174f05cddf9SRui Paulo 	if (os_strstr(capab, "[RX-STBC-12]"))
1175f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_RXSTBC_2;
1176f05cddf9SRui Paulo 	if (os_strstr(capab, "[RX-STBC-123]"))
1177f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_RXSTBC_3;
1178f05cddf9SRui Paulo 	if (os_strstr(capab, "[RX-STBC-1234]"))
1179f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_RXSTBC_4;
1180f05cddf9SRui Paulo 	if (os_strstr(capab, "[SU-BEAMFORMER]"))
11815b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE;
1182f05cddf9SRui Paulo 	if (os_strstr(capab, "[SU-BEAMFORMEE]"))
11835b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1184f05cddf9SRui Paulo 	if (os_strstr(capab, "[BF-ANTENNA-2]") &&
11855b9c547cSRui Paulo 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
11865b9c547cSRui Paulo 		conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1187325151a3SRui Paulo 	if (os_strstr(capab, "[BF-ANTENNA-3]") &&
1188325151a3SRui Paulo 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
1189325151a3SRui Paulo 		conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1190325151a3SRui Paulo 	if (os_strstr(capab, "[BF-ANTENNA-4]") &&
1191325151a3SRui Paulo 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
1192325151a3SRui Paulo 		conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1193f05cddf9SRui Paulo 	if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
11945b9c547cSRui Paulo 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
11955b9c547cSRui Paulo 		conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
1196325151a3SRui Paulo 	if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") &&
1197325151a3SRui Paulo 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
1198325151a3SRui Paulo 		conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
1199325151a3SRui Paulo 	if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") &&
1200325151a3SRui Paulo 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
1201325151a3SRui Paulo 		conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
1202f05cddf9SRui Paulo 	if (os_strstr(capab, "[MU-BEAMFORMER]"))
1203f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
1204f05cddf9SRui Paulo 	if (os_strstr(capab, "[VHT-TXOP-PS]"))
1205f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
1206f05cddf9SRui Paulo 	if (os_strstr(capab, "[HTC-VHT]"))
1207f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_HTC_VHT;
12085b9c547cSRui Paulo 	if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]"))
12095b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
12105b9c547cSRui Paulo 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]"))
12115b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6;
12125b9c547cSRui Paulo 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]"))
12135b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5;
12145b9c547cSRui Paulo 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]"))
12155b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4;
12165b9c547cSRui Paulo 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]"))
12175b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3;
12185b9c547cSRui Paulo 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]"))
12195b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2;
12205b9c547cSRui Paulo 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]"))
12215b9c547cSRui Paulo 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1;
1222f05cddf9SRui Paulo 	if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
1223f05cddf9SRui Paulo 	    (conf->vht_capab & VHT_CAP_HTC_VHT))
1224f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
1225f05cddf9SRui Paulo 	if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
1226f05cddf9SRui Paulo 	    (conf->vht_capab & VHT_CAP_HTC_VHT))
1227f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
1228f05cddf9SRui Paulo 	if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
1229f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
1230f05cddf9SRui Paulo 	if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
1231f05cddf9SRui Paulo 		conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
1232f05cddf9SRui Paulo 	return 0;
1233f05cddf9SRui Paulo }
1234f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211AC */
1235f05cddf9SRui Paulo 
1236f05cddf9SRui Paulo 
12374bc52338SCy Schubert #ifdef CONFIG_IEEE80211AX
12384bc52338SCy Schubert 
find_bit_offset(u8 val)12394bc52338SCy Schubert static u8 find_bit_offset(u8 val)
12404bc52338SCy Schubert {
12414bc52338SCy Schubert 	u8 res = 0;
12424bc52338SCy Schubert 
12434bc52338SCy Schubert 	for (; val; val >>= 1) {
12444bc52338SCy Schubert 		if (val & 1)
12454bc52338SCy Schubert 			break;
12464bc52338SCy Schubert 		res++;
12474bc52338SCy Schubert 	}
12484bc52338SCy Schubert 
12494bc52338SCy Schubert 	return res;
12504bc52338SCy Schubert }
12514bc52338SCy Schubert 
12524bc52338SCy Schubert 
set_he_cap(int val,u8 mask)12534bc52338SCy Schubert static u8 set_he_cap(int val, u8 mask)
12544bc52338SCy Schubert {
12554bc52338SCy Schubert 	return (u8) (mask & (val << find_bit_offset(mask)));
12564bc52338SCy Schubert }
12574bc52338SCy Schubert 
1258c1d255d3SCy Schubert 
hostapd_parse_he_srg_bitmap(u8 * bitmap,char * val)1259c1d255d3SCy Schubert static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val)
1260c1d255d3SCy Schubert {
1261c1d255d3SCy Schubert 	int bitpos;
1262c1d255d3SCy Schubert 	char *pos, *end;
1263c1d255d3SCy Schubert 
1264c1d255d3SCy Schubert 	os_memset(bitmap, 0, 8);
1265c1d255d3SCy Schubert 	pos = val;
1266c1d255d3SCy Schubert 	while (*pos != '\0') {
1267c1d255d3SCy Schubert 		end = os_strchr(pos, ' ');
1268c1d255d3SCy Schubert 		if (end)
1269c1d255d3SCy Schubert 			*end = '\0';
1270c1d255d3SCy Schubert 
1271c1d255d3SCy Schubert 		bitpos = atoi(pos);
1272c1d255d3SCy Schubert 		if (bitpos < 0 || bitpos > 64)
1273c1d255d3SCy Schubert 			return -1;
1274c1d255d3SCy Schubert 
1275c1d255d3SCy Schubert 		bitmap[bitpos / 8] |= BIT(bitpos % 8);
1276c1d255d3SCy Schubert 		if (!end)
1277c1d255d3SCy Schubert 			break;
1278c1d255d3SCy Schubert 		pos = end + 1;
1279c1d255d3SCy Schubert 	}
1280c1d255d3SCy Schubert 
1281c1d255d3SCy Schubert 	return 0;
1282c1d255d3SCy Schubert }
1283c1d255d3SCy Schubert 
12844bc52338SCy Schubert #endif /* CONFIG_IEEE80211AX */
12854bc52338SCy Schubert 
12864bc52338SCy Schubert 
1287f05cddf9SRui Paulo #ifdef CONFIG_INTERWORKING
parse_roaming_consortium(struct hostapd_bss_config * bss,char * pos,int line)1288f05cddf9SRui Paulo static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
1289f05cddf9SRui Paulo 				    int line)
1290e28a4053SRui Paulo {
1291f05cddf9SRui Paulo 	size_t len = os_strlen(pos);
1292f05cddf9SRui Paulo 	u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
1293e28a4053SRui Paulo 
1294f05cddf9SRui Paulo 	struct hostapd_roaming_consortium *rc;
1295f05cddf9SRui Paulo 
1296f05cddf9SRui Paulo 	if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
1297f05cddf9SRui Paulo 	    hexstr2bin(pos, oi, len / 2)) {
1298f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
1299f05cddf9SRui Paulo 			   "'%s'", line, pos);
1300f05cddf9SRui Paulo 		return -1;
1301f05cddf9SRui Paulo 	}
1302f05cddf9SRui Paulo 	len /= 2;
1303f05cddf9SRui Paulo 
1304f05cddf9SRui Paulo 	rc = os_realloc_array(bss->roaming_consortium,
1305f05cddf9SRui Paulo 			      bss->roaming_consortium_count + 1,
1306f05cddf9SRui Paulo 			      sizeof(struct hostapd_roaming_consortium));
1307f05cddf9SRui Paulo 	if (rc == NULL)
1308f05cddf9SRui Paulo 		return -1;
1309f05cddf9SRui Paulo 
1310f05cddf9SRui Paulo 	os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
1311f05cddf9SRui Paulo 	rc[bss->roaming_consortium_count].len = len;
1312f05cddf9SRui Paulo 
1313f05cddf9SRui Paulo 	bss->roaming_consortium = rc;
1314f05cddf9SRui Paulo 	bss->roaming_consortium_count++;
1315f05cddf9SRui Paulo 
1316f05cddf9SRui Paulo 	return 0;
1317e28a4053SRui Paulo }
1318e28a4053SRui Paulo 
1319f05cddf9SRui Paulo 
parse_lang_string(struct hostapd_lang_string ** array,unsigned int * count,char * pos)1320f05cddf9SRui Paulo static int parse_lang_string(struct hostapd_lang_string **array,
1321f05cddf9SRui Paulo 			     unsigned int *count, char *pos)
1322f05cddf9SRui Paulo {
13235b9c547cSRui Paulo 	char *sep, *str = NULL;
13245b9c547cSRui Paulo 	size_t clen, nlen, slen;
1325f05cddf9SRui Paulo 	struct hostapd_lang_string *ls;
13265b9c547cSRui Paulo 	int ret = -1;
13275b9c547cSRui Paulo 
13285b9c547cSRui Paulo 	if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) {
13295b9c547cSRui Paulo 		str = wpa_config_parse_string(pos, &slen);
13305b9c547cSRui Paulo 		if (!str)
13315b9c547cSRui Paulo 			return -1;
13325b9c547cSRui Paulo 		pos = str;
13335b9c547cSRui Paulo 	}
1334f05cddf9SRui Paulo 
1335f05cddf9SRui Paulo 	sep = os_strchr(pos, ':');
1336f05cddf9SRui Paulo 	if (sep == NULL)
13375b9c547cSRui Paulo 		goto fail;
1338f05cddf9SRui Paulo 	*sep++ = '\0';
1339f05cddf9SRui Paulo 
1340f05cddf9SRui Paulo 	clen = os_strlen(pos);
13415b9c547cSRui Paulo 	if (clen < 2 || clen > sizeof(ls->lang))
13425b9c547cSRui Paulo 		goto fail;
1343f05cddf9SRui Paulo 	nlen = os_strlen(sep);
1344f05cddf9SRui Paulo 	if (nlen > 252)
13455b9c547cSRui Paulo 		goto fail;
1346f05cddf9SRui Paulo 
1347f05cddf9SRui Paulo 	ls = os_realloc_array(*array, *count + 1,
1348f05cddf9SRui Paulo 			      sizeof(struct hostapd_lang_string));
1349f05cddf9SRui Paulo 	if (ls == NULL)
13505b9c547cSRui Paulo 		goto fail;
1351f05cddf9SRui Paulo 
1352f05cddf9SRui Paulo 	*array = ls;
1353f05cddf9SRui Paulo 	ls = &(*array)[*count];
1354f05cddf9SRui Paulo 	(*count)++;
1355f05cddf9SRui Paulo 
1356f05cddf9SRui Paulo 	os_memset(ls->lang, 0, sizeof(ls->lang));
1357f05cddf9SRui Paulo 	os_memcpy(ls->lang, pos, clen);
1358f05cddf9SRui Paulo 	ls->name_len = nlen;
1359f05cddf9SRui Paulo 	os_memcpy(ls->name, sep, nlen);
1360f05cddf9SRui Paulo 
13615b9c547cSRui Paulo 	ret = 0;
13625b9c547cSRui Paulo fail:
13635b9c547cSRui Paulo 	os_free(str);
13645b9c547cSRui Paulo 	return ret;
1365e28a4053SRui Paulo }
1366e28a4053SRui Paulo 
1367f05cddf9SRui Paulo 
parse_venue_name(struct hostapd_bss_config * bss,char * pos,int line)1368f05cddf9SRui Paulo static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
1369f05cddf9SRui Paulo 			    int line)
1370f05cddf9SRui Paulo {
1371f05cddf9SRui Paulo 	if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) {
1372f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
1373f05cddf9SRui Paulo 			   line, pos);
1374f05cddf9SRui Paulo 		return -1;
1375f05cddf9SRui Paulo 	}
1376f05cddf9SRui Paulo 	return 0;
1377e28a4053SRui Paulo }
1378e28a4053SRui Paulo 
1379e28a4053SRui Paulo 
parse_venue_url(struct hostapd_bss_config * bss,char * pos,int line)138085732ac8SCy Schubert static int parse_venue_url(struct hostapd_bss_config *bss, char *pos,
138185732ac8SCy Schubert 			    int line)
138285732ac8SCy Schubert {
138385732ac8SCy Schubert 	char *sep;
138485732ac8SCy Schubert 	size_t nlen;
138585732ac8SCy Schubert 	struct hostapd_venue_url *url;
138685732ac8SCy Schubert 	int ret = -1;
138785732ac8SCy Schubert 
138885732ac8SCy Schubert 	sep = os_strchr(pos, ':');
138985732ac8SCy Schubert 	if (!sep)
139085732ac8SCy Schubert 		goto fail;
139185732ac8SCy Schubert 	*sep++ = '\0';
139285732ac8SCy Schubert 
139385732ac8SCy Schubert 	nlen = os_strlen(sep);
139485732ac8SCy Schubert 	if (nlen > 254)
139585732ac8SCy Schubert 		goto fail;
139685732ac8SCy Schubert 
139785732ac8SCy Schubert 	url = os_realloc_array(bss->venue_url, bss->venue_url_count + 1,
139885732ac8SCy Schubert 			       sizeof(struct hostapd_venue_url));
139985732ac8SCy Schubert 	if (!url)
140085732ac8SCy Schubert 		goto fail;
140185732ac8SCy Schubert 
140285732ac8SCy Schubert 	bss->venue_url = url;
140385732ac8SCy Schubert 	url = &bss->venue_url[bss->venue_url_count++];
140485732ac8SCy Schubert 
140585732ac8SCy Schubert 	url->venue_number = atoi(pos);
140685732ac8SCy Schubert 	url->url_len = nlen;
140785732ac8SCy Schubert 	os_memcpy(url->url, sep, nlen);
140885732ac8SCy Schubert 
140985732ac8SCy Schubert 	ret = 0;
141085732ac8SCy Schubert fail:
141185732ac8SCy Schubert 	if (ret)
141285732ac8SCy Schubert 		wpa_printf(MSG_ERROR, "Line %d: Invalid venue_url '%s'",
141385732ac8SCy Schubert 			   line, pos);
141485732ac8SCy Schubert 	return ret;
141585732ac8SCy Schubert }
141685732ac8SCy Schubert 
141785732ac8SCy Schubert 
parse_3gpp_cell_net(struct hostapd_bss_config * bss,char * buf,int line)1418f05cddf9SRui Paulo static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
1419f05cddf9SRui Paulo 			       int line)
1420f05cddf9SRui Paulo {
1421f05cddf9SRui Paulo 	size_t count;
1422f05cddf9SRui Paulo 	char *pos;
1423f05cddf9SRui Paulo 	u8 *info = NULL, *ipos;
1424e28a4053SRui Paulo 
1425f05cddf9SRui Paulo 	/* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
1426f05cddf9SRui Paulo 
1427f05cddf9SRui Paulo 	count = 1;
1428f05cddf9SRui Paulo 	for (pos = buf; *pos; pos++) {
14295b9c547cSRui Paulo 		if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',')
1430f05cddf9SRui Paulo 			goto fail;
1431f05cddf9SRui Paulo 		if (*pos == ';')
1432f05cddf9SRui Paulo 			count++;
1433f05cddf9SRui Paulo 	}
1434f05cddf9SRui Paulo 	if (1 + count * 3 > 0x7f)
1435f05cddf9SRui Paulo 		goto fail;
1436f05cddf9SRui Paulo 
1437f05cddf9SRui Paulo 	info = os_zalloc(2 + 3 + count * 3);
1438f05cddf9SRui Paulo 	if (info == NULL)
1439f05cddf9SRui Paulo 		return -1;
1440f05cddf9SRui Paulo 
1441f05cddf9SRui Paulo 	ipos = info;
1442f05cddf9SRui Paulo 	*ipos++ = 0; /* GUD - Version 1 */
1443f05cddf9SRui Paulo 	*ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
1444f05cddf9SRui Paulo 	*ipos++ = 0; /* PLMN List IEI */
1445f05cddf9SRui Paulo 	/* ext(b8) | Length of PLMN List value contents(b7..1) */
1446f05cddf9SRui Paulo 	*ipos++ = 1 + count * 3;
1447f05cddf9SRui Paulo 	*ipos++ = count; /* Number of PLMNs */
1448f05cddf9SRui Paulo 
1449e28a4053SRui Paulo 	pos = buf;
1450f05cddf9SRui Paulo 	while (pos && *pos) {
1451f05cddf9SRui Paulo 		char *mcc, *mnc;
1452f05cddf9SRui Paulo 		size_t mnc_len;
1453e28a4053SRui Paulo 
1454f05cddf9SRui Paulo 		mcc = pos;
1455f05cddf9SRui Paulo 		mnc = os_strchr(pos, ',');
1456f05cddf9SRui Paulo 		if (mnc == NULL)
1457f05cddf9SRui Paulo 			goto fail;
1458f05cddf9SRui Paulo 		*mnc++ = '\0';
1459f05cddf9SRui Paulo 		pos = os_strchr(mnc, ';');
1460f05cddf9SRui Paulo 		if (pos)
1461f05cddf9SRui Paulo 			*pos++ = '\0';
1462f05cddf9SRui Paulo 
1463f05cddf9SRui Paulo 		mnc_len = os_strlen(mnc);
1464f05cddf9SRui Paulo 		if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3))
1465f05cddf9SRui Paulo 			goto fail;
1466f05cddf9SRui Paulo 
1467f05cddf9SRui Paulo 		/* BC coded MCC,MNC */
1468f05cddf9SRui Paulo 		/* MCC digit 2 | MCC digit 1 */
1469f05cddf9SRui Paulo 		*ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
1470f05cddf9SRui Paulo 		/* MNC digit 3 | MCC digit 3 */
1471f05cddf9SRui Paulo 		*ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
1472f05cddf9SRui Paulo 			(mcc[2] - '0');
1473f05cddf9SRui Paulo 		/* MNC digit 2 | MNC digit 1 */
1474f05cddf9SRui Paulo 		*ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
1475f05cddf9SRui Paulo 	}
1476f05cddf9SRui Paulo 
1477f05cddf9SRui Paulo 	os_free(bss->anqp_3gpp_cell_net);
1478f05cddf9SRui Paulo 	bss->anqp_3gpp_cell_net = info;
1479f05cddf9SRui Paulo 	bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
1480f05cddf9SRui Paulo 	wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
1481f05cddf9SRui Paulo 		    bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
1482f05cddf9SRui Paulo 
1483f05cddf9SRui Paulo 	return 0;
1484f05cddf9SRui Paulo 
1485f05cddf9SRui Paulo fail:
1486f05cddf9SRui Paulo 	wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s",
1487e28a4053SRui Paulo 		   line, buf);
1488f05cddf9SRui Paulo 	os_free(info);
1489f05cddf9SRui Paulo 	return -1;
1490e28a4053SRui Paulo }
1491f05cddf9SRui Paulo 
1492f05cddf9SRui Paulo 
parse_nai_realm(struct hostapd_bss_config * bss,char * buf,int line)1493f05cddf9SRui Paulo static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line)
1494f05cddf9SRui Paulo {
1495f05cddf9SRui Paulo 	struct hostapd_nai_realm_data *realm;
1496f05cddf9SRui Paulo 	size_t i, j, len;
1497f05cddf9SRui Paulo 	int *offsets;
1498f05cddf9SRui Paulo 	char *pos, *end, *rpos;
1499f05cddf9SRui Paulo 
1500f05cddf9SRui Paulo 	offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS,
1501f05cddf9SRui Paulo 			    sizeof(int));
1502f05cddf9SRui Paulo 	if (offsets == NULL)
1503f05cddf9SRui Paulo 		return -1;
1504f05cddf9SRui Paulo 
1505f05cddf9SRui Paulo 	for (i = 0; i < bss->nai_realm_count; i++) {
1506f05cddf9SRui Paulo 		realm = &bss->nai_realm_data[i];
1507f05cddf9SRui Paulo 		for (j = 0; j < MAX_NAI_REALMS; j++) {
1508f05cddf9SRui Paulo 			offsets[i * MAX_NAI_REALMS + j] =
1509f05cddf9SRui Paulo 				realm->realm[j] ?
1510f05cddf9SRui Paulo 				realm->realm[j] - realm->realm_buf : -1;
1511f05cddf9SRui Paulo 		}
1512f05cddf9SRui Paulo 	}
1513f05cddf9SRui Paulo 
1514f05cddf9SRui Paulo 	realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1,
1515f05cddf9SRui Paulo 				 sizeof(struct hostapd_nai_realm_data));
1516f05cddf9SRui Paulo 	if (realm == NULL) {
1517f05cddf9SRui Paulo 		os_free(offsets);
1518f05cddf9SRui Paulo 		return -1;
1519f05cddf9SRui Paulo 	}
1520f05cddf9SRui Paulo 	bss->nai_realm_data = realm;
1521f05cddf9SRui Paulo 
1522f05cddf9SRui Paulo 	/* patch the pointers after realloc */
1523f05cddf9SRui Paulo 	for (i = 0; i < bss->nai_realm_count; i++) {
1524f05cddf9SRui Paulo 		realm = &bss->nai_realm_data[i];
1525f05cddf9SRui Paulo 		for (j = 0; j < MAX_NAI_REALMS; j++) {
1526f05cddf9SRui Paulo 			int offs = offsets[i * MAX_NAI_REALMS + j];
1527f05cddf9SRui Paulo 			if (offs >= 0)
1528f05cddf9SRui Paulo 				realm->realm[j] = realm->realm_buf + offs;
1529f05cddf9SRui Paulo 			else
1530f05cddf9SRui Paulo 				realm->realm[j] = NULL;
1531f05cddf9SRui Paulo 		}
1532f05cddf9SRui Paulo 	}
1533f05cddf9SRui Paulo 	os_free(offsets);
1534f05cddf9SRui Paulo 
1535f05cddf9SRui Paulo 	realm = &bss->nai_realm_data[bss->nai_realm_count];
1536f05cddf9SRui Paulo 	os_memset(realm, 0, sizeof(*realm));
1537f05cddf9SRui Paulo 
1538f05cddf9SRui Paulo 	pos = buf;
1539f05cddf9SRui Paulo 	realm->encoding = atoi(pos);
1540f05cddf9SRui Paulo 	pos = os_strchr(pos, ',');
1541f05cddf9SRui Paulo 	if (pos == NULL)
1542f05cddf9SRui Paulo 		goto fail;
1543e28a4053SRui Paulo 	pos++;
1544e28a4053SRui Paulo 
1545f05cddf9SRui Paulo 	end = os_strchr(pos, ',');
1546f05cddf9SRui Paulo 	if (end) {
1547f05cddf9SRui Paulo 		len = end - pos;
1548f05cddf9SRui Paulo 		*end = '\0';
1549f05cddf9SRui Paulo 	} else {
1550f05cddf9SRui Paulo 		len = os_strlen(pos);
1551f05cddf9SRui Paulo 	}
1552f05cddf9SRui Paulo 
1553f05cddf9SRui Paulo 	if (len > MAX_NAI_REALMLEN) {
1554f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d "
1555f05cddf9SRui Paulo 			   "characters)", (int) len, MAX_NAI_REALMLEN);
1556f05cddf9SRui Paulo 		goto fail;
1557f05cddf9SRui Paulo 	}
1558f05cddf9SRui Paulo 	os_memcpy(realm->realm_buf, pos, len);
1559f05cddf9SRui Paulo 
1560f05cddf9SRui Paulo 	if (end)
1561f05cddf9SRui Paulo 		pos = end + 1;
1562f05cddf9SRui Paulo 	else
1563f05cddf9SRui Paulo 		pos = NULL;
1564f05cddf9SRui Paulo 
1565f05cddf9SRui Paulo 	while (pos && *pos) {
1566f05cddf9SRui Paulo 		struct hostapd_nai_realm_eap *eap;
1567f05cddf9SRui Paulo 
1568f05cddf9SRui Paulo 		if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) {
1569f05cddf9SRui Paulo 			wpa_printf(MSG_ERROR, "Too many EAP methods");
1570f05cddf9SRui Paulo 			goto fail;
1571f05cddf9SRui Paulo 		}
1572f05cddf9SRui Paulo 
1573f05cddf9SRui Paulo 		eap = &realm->eap_method[realm->eap_method_count];
1574f05cddf9SRui Paulo 		realm->eap_method_count++;
1575f05cddf9SRui Paulo 
1576f05cddf9SRui Paulo 		end = os_strchr(pos, ',');
1577f05cddf9SRui Paulo 		if (end == NULL)
1578f05cddf9SRui Paulo 			end = pos + os_strlen(pos);
1579f05cddf9SRui Paulo 
1580f05cddf9SRui Paulo 		eap->eap_method = atoi(pos);
1581f05cddf9SRui Paulo 		for (;;) {
1582f05cddf9SRui Paulo 			pos = os_strchr(pos, '[');
1583f05cddf9SRui Paulo 			if (pos == NULL || pos > end)
1584f05cddf9SRui Paulo 				break;
1585f05cddf9SRui Paulo 			pos++;
1586f05cddf9SRui Paulo 			if (eap->num_auths >= MAX_NAI_AUTH_TYPES) {
1587f05cddf9SRui Paulo 				wpa_printf(MSG_ERROR, "Too many auth params");
1588f05cddf9SRui Paulo 				goto fail;
1589f05cddf9SRui Paulo 			}
1590f05cddf9SRui Paulo 			eap->auth_id[eap->num_auths] = atoi(pos);
1591f05cddf9SRui Paulo 			pos = os_strchr(pos, ':');
1592f05cddf9SRui Paulo 			if (pos == NULL || pos > end)
1593f05cddf9SRui Paulo 				goto fail;
1594f05cddf9SRui Paulo 			pos++;
1595f05cddf9SRui Paulo 			eap->auth_val[eap->num_auths] = atoi(pos);
1596f05cddf9SRui Paulo 			pos = os_strchr(pos, ']');
1597f05cddf9SRui Paulo 			if (pos == NULL || pos > end)
1598f05cddf9SRui Paulo 				goto fail;
1599f05cddf9SRui Paulo 			pos++;
1600f05cddf9SRui Paulo 			eap->num_auths++;
1601f05cddf9SRui Paulo 		}
1602f05cddf9SRui Paulo 
1603f05cddf9SRui Paulo 		if (*end != ',')
1604f05cddf9SRui Paulo 			break;
1605f05cddf9SRui Paulo 
1606f05cddf9SRui Paulo 		pos = end + 1;
1607f05cddf9SRui Paulo 	}
1608f05cddf9SRui Paulo 
1609f05cddf9SRui Paulo 	/* Split realm list into null terminated realms */
1610f05cddf9SRui Paulo 	rpos = realm->realm_buf;
1611f05cddf9SRui Paulo 	i = 0;
1612f05cddf9SRui Paulo 	while (*rpos) {
1613f05cddf9SRui Paulo 		if (i >= MAX_NAI_REALMS) {
1614f05cddf9SRui Paulo 			wpa_printf(MSG_ERROR, "Too many realms");
1615f05cddf9SRui Paulo 			goto fail;
1616f05cddf9SRui Paulo 		}
1617f05cddf9SRui Paulo 		realm->realm[i++] = rpos;
1618f05cddf9SRui Paulo 		rpos = os_strchr(rpos, ';');
1619f05cddf9SRui Paulo 		if (rpos == NULL)
1620f05cddf9SRui Paulo 			break;
1621f05cddf9SRui Paulo 		*rpos++ = '\0';
1622f05cddf9SRui Paulo 	}
1623f05cddf9SRui Paulo 
1624f05cddf9SRui Paulo 	bss->nai_realm_count++;
1625f05cddf9SRui Paulo 
1626f05cddf9SRui Paulo 	return 0;
1627f05cddf9SRui Paulo 
1628f05cddf9SRui Paulo fail:
1629f05cddf9SRui Paulo 	wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf);
1630f05cddf9SRui Paulo 	return -1;
1631f05cddf9SRui Paulo }
1632f05cddf9SRui Paulo 
16335b9c547cSRui Paulo 
parse_anqp_elem(struct hostapd_bss_config * bss,char * buf,int line)1634780fb4a2SCy Schubert static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
1635780fb4a2SCy Schubert {
1636780fb4a2SCy Schubert 	char *delim;
1637780fb4a2SCy Schubert 	u16 infoid;
1638780fb4a2SCy Schubert 	size_t len;
1639780fb4a2SCy Schubert 	struct wpabuf *payload;
1640780fb4a2SCy Schubert 	struct anqp_element *elem;
1641780fb4a2SCy Schubert 
1642780fb4a2SCy Schubert 	delim = os_strchr(buf, ':');
1643780fb4a2SCy Schubert 	if (!delim)
1644780fb4a2SCy Schubert 		return -1;
1645780fb4a2SCy Schubert 	delim++;
1646780fb4a2SCy Schubert 	infoid = atoi(buf);
1647780fb4a2SCy Schubert 	len = os_strlen(delim);
1648780fb4a2SCy Schubert 	if (len & 1)
1649780fb4a2SCy Schubert 		return -1;
1650780fb4a2SCy Schubert 	len /= 2;
1651780fb4a2SCy Schubert 	payload = wpabuf_alloc(len);
1652780fb4a2SCy Schubert 	if (!payload)
1653780fb4a2SCy Schubert 		return -1;
1654780fb4a2SCy Schubert 	if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) {
1655780fb4a2SCy Schubert 		wpabuf_free(payload);
1656780fb4a2SCy Schubert 		return -1;
1657780fb4a2SCy Schubert 	}
1658780fb4a2SCy Schubert 
1659780fb4a2SCy Schubert 	dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) {
1660780fb4a2SCy Schubert 		if (elem->infoid == infoid) {
1661780fb4a2SCy Schubert 			/* Update existing entry */
1662780fb4a2SCy Schubert 			wpabuf_free(elem->payload);
1663780fb4a2SCy Schubert 			elem->payload = payload;
1664780fb4a2SCy Schubert 			return 0;
1665780fb4a2SCy Schubert 		}
1666780fb4a2SCy Schubert 	}
1667780fb4a2SCy Schubert 
1668780fb4a2SCy Schubert 	/* Add a new entry */
1669780fb4a2SCy Schubert 	elem = os_zalloc(sizeof(*elem));
1670780fb4a2SCy Schubert 	if (!elem) {
1671780fb4a2SCy Schubert 		wpabuf_free(payload);
1672780fb4a2SCy Schubert 		return -1;
1673780fb4a2SCy Schubert 	}
1674780fb4a2SCy Schubert 	elem->infoid = infoid;
1675780fb4a2SCy Schubert 	elem->payload = payload;
1676780fb4a2SCy Schubert 	dl_list_add(&bss->anqp_elem, &elem->list);
1677780fb4a2SCy Schubert 
1678780fb4a2SCy Schubert 	return 0;
1679780fb4a2SCy Schubert }
1680780fb4a2SCy Schubert 
1681*a90b9d01SCy Schubert #endif /* CONFIG_INTERWORKING */
1682*a90b9d01SCy Schubert 
1683780fb4a2SCy Schubert 
parse_qos_map_set(struct hostapd_bss_config * bss,char * buf,int line)16845b9c547cSRui Paulo static int parse_qos_map_set(struct hostapd_bss_config *bss,
16855b9c547cSRui Paulo 			     char *buf, int line)
16865b9c547cSRui Paulo {
16875b9c547cSRui Paulo 	u8 qos_map_set[16 + 2 * 21], count = 0;
16885b9c547cSRui Paulo 	char *pos = buf;
16895b9c547cSRui Paulo 	int val;
16905b9c547cSRui Paulo 
16915b9c547cSRui Paulo 	for (;;) {
16925b9c547cSRui Paulo 		if (count == sizeof(qos_map_set)) {
16935b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set "
16945b9c547cSRui Paulo 				   "parameters '%s'", line, buf);
16955b9c547cSRui Paulo 			return -1;
16965b9c547cSRui Paulo 		}
16975b9c547cSRui Paulo 
16985b9c547cSRui Paulo 		val = atoi(pos);
16995b9c547cSRui Paulo 		if (val > 255 || val < 0) {
17005b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set "
17015b9c547cSRui Paulo 				   "'%s'", line, buf);
17025b9c547cSRui Paulo 			return -1;
17035b9c547cSRui Paulo 		}
17045b9c547cSRui Paulo 
17055b9c547cSRui Paulo 		qos_map_set[count++] = val;
17065b9c547cSRui Paulo 		pos = os_strchr(pos, ',');
17075b9c547cSRui Paulo 		if (!pos)
17085b9c547cSRui Paulo 			break;
17095b9c547cSRui Paulo 		pos++;
17105b9c547cSRui Paulo 	}
17115b9c547cSRui Paulo 
17125b9c547cSRui Paulo 	if (count < 16 || count & 1) {
17135b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'",
17145b9c547cSRui Paulo 			   line, buf);
17155b9c547cSRui Paulo 		return -1;
17165b9c547cSRui Paulo 	}
17175b9c547cSRui Paulo 
17185b9c547cSRui Paulo 	os_memcpy(bss->qos_map_set, qos_map_set, count);
17195b9c547cSRui Paulo 	bss->qos_map_set_len = count;
17205b9c547cSRui Paulo 
17215b9c547cSRui Paulo 	return 0;
17225b9c547cSRui Paulo }
17235b9c547cSRui Paulo 
1724f05cddf9SRui Paulo 
1725f05cddf9SRui Paulo #ifdef CONFIG_HS20
hs20_parse_conn_capab(struct hostapd_bss_config * bss,char * buf,int line)1726f05cddf9SRui Paulo static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
1727f05cddf9SRui Paulo 				 int line)
1728f05cddf9SRui Paulo {
1729f05cddf9SRui Paulo 	u8 *conn_cap;
1730f05cddf9SRui Paulo 	char *pos;
1731f05cddf9SRui Paulo 
1732f05cddf9SRui Paulo 	if (bss->hs20_connection_capability_len >= 0xfff0)
1733f05cddf9SRui Paulo 		return -1;
1734f05cddf9SRui Paulo 
1735f05cddf9SRui Paulo 	conn_cap = os_realloc(bss->hs20_connection_capability,
1736f05cddf9SRui Paulo 			      bss->hs20_connection_capability_len + 4);
1737f05cddf9SRui Paulo 	if (conn_cap == NULL)
1738f05cddf9SRui Paulo 		return -1;
1739f05cddf9SRui Paulo 
1740f05cddf9SRui Paulo 	bss->hs20_connection_capability = conn_cap;
1741f05cddf9SRui Paulo 	conn_cap += bss->hs20_connection_capability_len;
1742f05cddf9SRui Paulo 	pos = buf;
1743f05cddf9SRui Paulo 	conn_cap[0] = atoi(pos);
1744f05cddf9SRui Paulo 	pos = os_strchr(pos, ':');
1745f05cddf9SRui Paulo 	if (pos == NULL)
1746f05cddf9SRui Paulo 		return -1;
1747f05cddf9SRui Paulo 	pos++;
1748f05cddf9SRui Paulo 	WPA_PUT_LE16(conn_cap + 1, atoi(pos));
1749f05cddf9SRui Paulo 	pos = os_strchr(pos, ':');
1750f05cddf9SRui Paulo 	if (pos == NULL)
1751f05cddf9SRui Paulo 		return -1;
1752f05cddf9SRui Paulo 	pos++;
1753f05cddf9SRui Paulo 	conn_cap[3] = atoi(pos);
1754f05cddf9SRui Paulo 	bss->hs20_connection_capability_len += 4;
1755f05cddf9SRui Paulo 
1756f05cddf9SRui Paulo 	return 0;
1757f05cddf9SRui Paulo }
1758f05cddf9SRui Paulo 
1759f05cddf9SRui Paulo 
hs20_parse_wan_metrics(struct hostapd_bss_config * bss,char * buf,int line)1760f05cddf9SRui Paulo static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf,
1761f05cddf9SRui Paulo 				  int line)
1762f05cddf9SRui Paulo {
1763f05cddf9SRui Paulo 	u8 *wan_metrics;
1764f05cddf9SRui Paulo 	char *pos;
1765f05cddf9SRui Paulo 
1766f05cddf9SRui Paulo 	/* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */
1767f05cddf9SRui Paulo 
1768f05cddf9SRui Paulo 	wan_metrics = os_zalloc(13);
1769f05cddf9SRui Paulo 	if (wan_metrics == NULL)
1770f05cddf9SRui Paulo 		return -1;
1771f05cddf9SRui Paulo 
1772f05cddf9SRui Paulo 	pos = buf;
1773f05cddf9SRui Paulo 	/* WAN Info */
1774f05cddf9SRui Paulo 	if (hexstr2bin(pos, wan_metrics, 1) < 0)
1775f05cddf9SRui Paulo 		goto fail;
1776f05cddf9SRui Paulo 	pos += 2;
1777f05cddf9SRui Paulo 	if (*pos != ':')
1778f05cddf9SRui Paulo 		goto fail;
1779f05cddf9SRui Paulo 	pos++;
1780f05cddf9SRui Paulo 
1781f05cddf9SRui Paulo 	/* Downlink Speed */
1782f05cddf9SRui Paulo 	WPA_PUT_LE32(wan_metrics + 1, atoi(pos));
1783f05cddf9SRui Paulo 	pos = os_strchr(pos, ':');
1784f05cddf9SRui Paulo 	if (pos == NULL)
1785f05cddf9SRui Paulo 		goto fail;
1786f05cddf9SRui Paulo 	pos++;
1787f05cddf9SRui Paulo 
1788f05cddf9SRui Paulo 	/* Uplink Speed */
1789f05cddf9SRui Paulo 	WPA_PUT_LE32(wan_metrics + 5, atoi(pos));
1790f05cddf9SRui Paulo 	pos = os_strchr(pos, ':');
1791f05cddf9SRui Paulo 	if (pos == NULL)
1792f05cddf9SRui Paulo 		goto fail;
1793f05cddf9SRui Paulo 	pos++;
1794f05cddf9SRui Paulo 
1795f05cddf9SRui Paulo 	/* Downlink Load */
1796f05cddf9SRui Paulo 	wan_metrics[9] = atoi(pos);
1797f05cddf9SRui Paulo 	pos = os_strchr(pos, ':');
1798f05cddf9SRui Paulo 	if (pos == NULL)
1799f05cddf9SRui Paulo 		goto fail;
1800f05cddf9SRui Paulo 	pos++;
1801f05cddf9SRui Paulo 
1802f05cddf9SRui Paulo 	/* Uplink Load */
1803f05cddf9SRui Paulo 	wan_metrics[10] = atoi(pos);
1804f05cddf9SRui Paulo 	pos = os_strchr(pos, ':');
1805f05cddf9SRui Paulo 	if (pos == NULL)
1806f05cddf9SRui Paulo 		goto fail;
1807f05cddf9SRui Paulo 	pos++;
1808f05cddf9SRui Paulo 
1809f05cddf9SRui Paulo 	/* LMD */
1810f05cddf9SRui Paulo 	WPA_PUT_LE16(wan_metrics + 11, atoi(pos));
1811f05cddf9SRui Paulo 
1812f05cddf9SRui Paulo 	os_free(bss->hs20_wan_metrics);
1813f05cddf9SRui Paulo 	bss->hs20_wan_metrics = wan_metrics;
1814f05cddf9SRui Paulo 
1815f05cddf9SRui Paulo 	return 0;
1816f05cddf9SRui Paulo 
1817f05cddf9SRui Paulo fail:
1818f05cddf9SRui Paulo 	wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'",
18195b9c547cSRui Paulo 		   line, buf);
1820f05cddf9SRui Paulo 	os_free(wan_metrics);
1821f05cddf9SRui Paulo 	return -1;
1822f05cddf9SRui Paulo }
1823f05cddf9SRui Paulo 
1824f05cddf9SRui Paulo 
hs20_parse_oper_friendly_name(struct hostapd_bss_config * bss,char * pos,int line)1825f05cddf9SRui Paulo static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
1826f05cddf9SRui Paulo 					 char *pos, int line)
1827f05cddf9SRui Paulo {
1828f05cddf9SRui Paulo 	if (parse_lang_string(&bss->hs20_oper_friendly_name,
1829f05cddf9SRui Paulo 			      &bss->hs20_oper_friendly_name_count, pos)) {
1830f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid "
1831f05cddf9SRui Paulo 			   "hs20_oper_friendly_name '%s'", line, pos);
1832f05cddf9SRui Paulo 		return -1;
1833f05cddf9SRui Paulo 	}
1834f05cddf9SRui Paulo 	return 0;
1835f05cddf9SRui Paulo }
18365b9c547cSRui Paulo 
18375b9c547cSRui Paulo 
hs20_parse_icon(struct hostapd_bss_config * bss,char * pos)18385b9c547cSRui Paulo static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
18395b9c547cSRui Paulo {
18405b9c547cSRui Paulo 	struct hs20_icon *icon;
18415b9c547cSRui Paulo 	char *end;
18425b9c547cSRui Paulo 
18435b9c547cSRui Paulo 	icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
18445b9c547cSRui Paulo 				sizeof(struct hs20_icon));
18455b9c547cSRui Paulo 	if (icon == NULL)
18465b9c547cSRui Paulo 		return -1;
18475b9c547cSRui Paulo 	bss->hs20_icons = icon;
18485b9c547cSRui Paulo 	icon = &bss->hs20_icons[bss->hs20_icons_count];
18495b9c547cSRui Paulo 	os_memset(icon, 0, sizeof(*icon));
18505b9c547cSRui Paulo 
18515b9c547cSRui Paulo 	icon->width = atoi(pos);
18525b9c547cSRui Paulo 	pos = os_strchr(pos, ':');
18535b9c547cSRui Paulo 	if (pos == NULL)
18545b9c547cSRui Paulo 		return -1;
18555b9c547cSRui Paulo 	pos++;
18565b9c547cSRui Paulo 
18575b9c547cSRui Paulo 	icon->height = atoi(pos);
18585b9c547cSRui Paulo 	pos = os_strchr(pos, ':');
18595b9c547cSRui Paulo 	if (pos == NULL)
18605b9c547cSRui Paulo 		return -1;
18615b9c547cSRui Paulo 	pos++;
18625b9c547cSRui Paulo 
18635b9c547cSRui Paulo 	end = os_strchr(pos, ':');
18645b9c547cSRui Paulo 	if (end == NULL || end - pos > 3)
18655b9c547cSRui Paulo 		return -1;
18665b9c547cSRui Paulo 	os_memcpy(icon->language, pos, end - pos);
18675b9c547cSRui Paulo 	pos = end + 1;
18685b9c547cSRui Paulo 
18695b9c547cSRui Paulo 	end = os_strchr(pos, ':');
18705b9c547cSRui Paulo 	if (end == NULL || end - pos > 255)
18715b9c547cSRui Paulo 		return -1;
18725b9c547cSRui Paulo 	os_memcpy(icon->type, pos, end - pos);
18735b9c547cSRui Paulo 	pos = end + 1;
18745b9c547cSRui Paulo 
18755b9c547cSRui Paulo 	end = os_strchr(pos, ':');
18765b9c547cSRui Paulo 	if (end == NULL || end - pos > 255)
18775b9c547cSRui Paulo 		return -1;
18785b9c547cSRui Paulo 	os_memcpy(icon->name, pos, end - pos);
18795b9c547cSRui Paulo 	pos = end + 1;
18805b9c547cSRui Paulo 
18815b9c547cSRui Paulo 	if (os_strlen(pos) > 255)
18825b9c547cSRui Paulo 		return -1;
18835b9c547cSRui Paulo 	os_memcpy(icon->file, pos, os_strlen(pos));
18845b9c547cSRui Paulo 
18855b9c547cSRui Paulo 	bss->hs20_icons_count++;
18865b9c547cSRui Paulo 
18875b9c547cSRui Paulo 	return 0;
18885b9c547cSRui Paulo }
18895b9c547cSRui Paulo 
18905b9c547cSRui Paulo 
hs20_parse_osu_ssid(struct hostapd_bss_config * bss,char * pos,int line)18915b9c547cSRui Paulo static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
18925b9c547cSRui Paulo 			       char *pos, int line)
18935b9c547cSRui Paulo {
18945b9c547cSRui Paulo 	size_t slen;
18955b9c547cSRui Paulo 	char *str;
18965b9c547cSRui Paulo 
18975b9c547cSRui Paulo 	str = wpa_config_parse_string(pos, &slen);
1898325151a3SRui Paulo 	if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
18995b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
19005b9c547cSRui Paulo 		os_free(str);
19015b9c547cSRui Paulo 		return -1;
19025b9c547cSRui Paulo 	}
19035b9c547cSRui Paulo 
19045b9c547cSRui Paulo 	os_memcpy(bss->osu_ssid, str, slen);
19055b9c547cSRui Paulo 	bss->osu_ssid_len = slen;
19065b9c547cSRui Paulo 	os_free(str);
19075b9c547cSRui Paulo 
19085b9c547cSRui Paulo 	return 0;
19095b9c547cSRui Paulo }
19105b9c547cSRui Paulo 
19115b9c547cSRui Paulo 
hs20_parse_osu_server_uri(struct hostapd_bss_config * bss,char * pos,int line)19125b9c547cSRui Paulo static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
19135b9c547cSRui Paulo 				     char *pos, int line)
19145b9c547cSRui Paulo {
19155b9c547cSRui Paulo 	struct hs20_osu_provider *p;
19165b9c547cSRui Paulo 
19175b9c547cSRui Paulo 	p = os_realloc_array(bss->hs20_osu_providers,
19185b9c547cSRui Paulo 			     bss->hs20_osu_providers_count + 1, sizeof(*p));
19195b9c547cSRui Paulo 	if (p == NULL)
19205b9c547cSRui Paulo 		return -1;
19215b9c547cSRui Paulo 
19225b9c547cSRui Paulo 	bss->hs20_osu_providers = p;
19235b9c547cSRui Paulo 	bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
19245b9c547cSRui Paulo 	bss->hs20_osu_providers_count++;
19255b9c547cSRui Paulo 	os_memset(bss->last_osu, 0, sizeof(*p));
19265b9c547cSRui Paulo 	bss->last_osu->server_uri = os_strdup(pos);
19275b9c547cSRui Paulo 
19285b9c547cSRui Paulo 	return 0;
19295b9c547cSRui Paulo }
19305b9c547cSRui Paulo 
19315b9c547cSRui Paulo 
hs20_parse_osu_friendly_name(struct hostapd_bss_config * bss,char * pos,int line)19325b9c547cSRui Paulo static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
19335b9c547cSRui Paulo 					char *pos, int line)
19345b9c547cSRui Paulo {
19355b9c547cSRui Paulo 	if (bss->last_osu == NULL) {
19365b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
19375b9c547cSRui Paulo 		return -1;
19385b9c547cSRui Paulo 	}
19395b9c547cSRui Paulo 
19405b9c547cSRui Paulo 	if (parse_lang_string(&bss->last_osu->friendly_name,
19415b9c547cSRui Paulo 			      &bss->last_osu->friendly_name_count, pos)) {
19425b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
19435b9c547cSRui Paulo 			   line, pos);
19445b9c547cSRui Paulo 		return -1;
19455b9c547cSRui Paulo 	}
19465b9c547cSRui Paulo 
19475b9c547cSRui Paulo 	return 0;
19485b9c547cSRui Paulo }
19495b9c547cSRui Paulo 
19505b9c547cSRui Paulo 
hs20_parse_osu_nai(struct hostapd_bss_config * bss,char * pos,int line)19515b9c547cSRui Paulo static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
19525b9c547cSRui Paulo 			      char *pos, int line)
19535b9c547cSRui Paulo {
19545b9c547cSRui Paulo 	if (bss->last_osu == NULL) {
19555b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
19565b9c547cSRui Paulo 		return -1;
19575b9c547cSRui Paulo 	}
19585b9c547cSRui Paulo 
19595b9c547cSRui Paulo 	os_free(bss->last_osu->osu_nai);
19605b9c547cSRui Paulo 	bss->last_osu->osu_nai = os_strdup(pos);
19615b9c547cSRui Paulo 	if (bss->last_osu->osu_nai == NULL)
19625b9c547cSRui Paulo 		return -1;
19635b9c547cSRui Paulo 
19645b9c547cSRui Paulo 	return 0;
19655b9c547cSRui Paulo }
19665b9c547cSRui Paulo 
19675b9c547cSRui Paulo 
hs20_parse_osu_nai2(struct hostapd_bss_config * bss,char * pos,int line)196885732ac8SCy Schubert static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss,
196985732ac8SCy Schubert 			       char *pos, int line)
197085732ac8SCy Schubert {
197185732ac8SCy Schubert 	if (bss->last_osu == NULL) {
197285732ac8SCy Schubert 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
197385732ac8SCy Schubert 		return -1;
197485732ac8SCy Schubert 	}
197585732ac8SCy Schubert 
197685732ac8SCy Schubert 	os_free(bss->last_osu->osu_nai2);
197785732ac8SCy Schubert 	bss->last_osu->osu_nai2 = os_strdup(pos);
197885732ac8SCy Schubert 	if (bss->last_osu->osu_nai2 == NULL)
197985732ac8SCy Schubert 		return -1;
198085732ac8SCy Schubert 	bss->hs20_osu_providers_nai_count++;
198185732ac8SCy Schubert 
198285732ac8SCy Schubert 	return 0;
198385732ac8SCy Schubert }
198485732ac8SCy Schubert 
198585732ac8SCy Schubert 
hs20_parse_osu_method_list(struct hostapd_bss_config * bss,char * pos,int line)19865b9c547cSRui Paulo static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
19875b9c547cSRui Paulo 				      int line)
19885b9c547cSRui Paulo {
19895b9c547cSRui Paulo 	if (bss->last_osu == NULL) {
19905b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
19915b9c547cSRui Paulo 		return -1;
19925b9c547cSRui Paulo 	}
19935b9c547cSRui Paulo 
19945b9c547cSRui Paulo 	if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
19955b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
19965b9c547cSRui Paulo 		return -1;
19975b9c547cSRui Paulo 	}
19985b9c547cSRui Paulo 
19995b9c547cSRui Paulo 	return 0;
20005b9c547cSRui Paulo }
20015b9c547cSRui Paulo 
20025b9c547cSRui Paulo 
hs20_parse_osu_icon(struct hostapd_bss_config * bss,char * pos,int line)20035b9c547cSRui Paulo static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
20045b9c547cSRui Paulo 			       int line)
20055b9c547cSRui Paulo {
20065b9c547cSRui Paulo 	char **n;
20075b9c547cSRui Paulo 	struct hs20_osu_provider *p = bss->last_osu;
20085b9c547cSRui Paulo 
20095b9c547cSRui Paulo 	if (p == NULL) {
20105b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
20115b9c547cSRui Paulo 		return -1;
20125b9c547cSRui Paulo 	}
20135b9c547cSRui Paulo 
20145b9c547cSRui Paulo 	n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
20155b9c547cSRui Paulo 	if (n == NULL)
20165b9c547cSRui Paulo 		return -1;
20175b9c547cSRui Paulo 	p->icons = n;
20185b9c547cSRui Paulo 	p->icons[p->icons_count] = os_strdup(pos);
20195b9c547cSRui Paulo 	if (p->icons[p->icons_count] == NULL)
20205b9c547cSRui Paulo 		return -1;
20215b9c547cSRui Paulo 	p->icons_count++;
20225b9c547cSRui Paulo 
20235b9c547cSRui Paulo 	return 0;
20245b9c547cSRui Paulo }
20255b9c547cSRui Paulo 
20265b9c547cSRui Paulo 
hs20_parse_osu_service_desc(struct hostapd_bss_config * bss,char * pos,int line)20275b9c547cSRui Paulo static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
20285b9c547cSRui Paulo 				       char *pos, int line)
20295b9c547cSRui Paulo {
20305b9c547cSRui Paulo 	if (bss->last_osu == NULL) {
20315b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
20325b9c547cSRui Paulo 		return -1;
20335b9c547cSRui Paulo 	}
20345b9c547cSRui Paulo 
20355b9c547cSRui Paulo 	if (parse_lang_string(&bss->last_osu->service_desc,
20365b9c547cSRui Paulo 			      &bss->last_osu->service_desc_count, pos)) {
20375b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
20385b9c547cSRui Paulo 			   line, pos);
20395b9c547cSRui Paulo 		return -1;
20405b9c547cSRui Paulo 	}
20415b9c547cSRui Paulo 
20425b9c547cSRui Paulo 	return 0;
20435b9c547cSRui Paulo }
20445b9c547cSRui Paulo 
204585732ac8SCy Schubert 
hs20_parse_operator_icon(struct hostapd_bss_config * bss,char * pos,int line)204685732ac8SCy Schubert static int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos,
204785732ac8SCy Schubert 				    int line)
204885732ac8SCy Schubert {
204985732ac8SCy Schubert 	char **n;
205085732ac8SCy Schubert 
205185732ac8SCy Schubert 	n = os_realloc_array(bss->hs20_operator_icon,
205285732ac8SCy Schubert 			     bss->hs20_operator_icon_count + 1, sizeof(char *));
205385732ac8SCy Schubert 	if (!n)
205485732ac8SCy Schubert 		return -1;
205585732ac8SCy Schubert 	bss->hs20_operator_icon = n;
205685732ac8SCy Schubert 	bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos);
205785732ac8SCy Schubert 	if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count])
205885732ac8SCy Schubert 		return -1;
205985732ac8SCy Schubert 	bss->hs20_operator_icon_count++;
206085732ac8SCy Schubert 
206185732ac8SCy Schubert 	return 0;
206285732ac8SCy Schubert }
206385732ac8SCy Schubert 
2064f05cddf9SRui Paulo #endif /* CONFIG_HS20 */
2065f05cddf9SRui Paulo 
2066f05cddf9SRui Paulo 
20675b9c547cSRui Paulo #ifdef CONFIG_ACS
hostapd_config_parse_acs_chan_bias(struct hostapd_config * conf,char * pos)20685b9c547cSRui Paulo static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
20695b9c547cSRui Paulo 					      char *pos)
20705b9c547cSRui Paulo {
20715b9c547cSRui Paulo 	struct acs_bias *bias = NULL, *tmp;
20725b9c547cSRui Paulo 	unsigned int num = 0;
20735b9c547cSRui Paulo 	char *end;
20745b9c547cSRui Paulo 
20755b9c547cSRui Paulo 	while (*pos) {
20765b9c547cSRui Paulo 		tmp = os_realloc_array(bias, num + 1, sizeof(*bias));
20775b9c547cSRui Paulo 		if (!tmp)
20785b9c547cSRui Paulo 			goto fail;
20795b9c547cSRui Paulo 		bias = tmp;
20805b9c547cSRui Paulo 
20815b9c547cSRui Paulo 		bias[num].channel = atoi(pos);
20825b9c547cSRui Paulo 		if (bias[num].channel <= 0)
20835b9c547cSRui Paulo 			goto fail;
20845b9c547cSRui Paulo 		pos = os_strchr(pos, ':');
20855b9c547cSRui Paulo 		if (!pos)
20865b9c547cSRui Paulo 			goto fail;
20875b9c547cSRui Paulo 		pos++;
20885b9c547cSRui Paulo 		bias[num].bias = strtod(pos, &end);
20895b9c547cSRui Paulo 		if (end == pos || bias[num].bias < 0.0)
20905b9c547cSRui Paulo 			goto fail;
20915b9c547cSRui Paulo 		pos = end;
20925b9c547cSRui Paulo 		if (*pos != ' ' && *pos != '\0')
20935b9c547cSRui Paulo 			goto fail;
20945b9c547cSRui Paulo 		num++;
20955b9c547cSRui Paulo 	}
20965b9c547cSRui Paulo 
20975b9c547cSRui Paulo 	os_free(conf->acs_chan_bias);
20985b9c547cSRui Paulo 	conf->acs_chan_bias = bias;
20995b9c547cSRui Paulo 	conf->num_acs_chan_bias = num;
21005b9c547cSRui Paulo 
21015b9c547cSRui Paulo 	return 0;
21025b9c547cSRui Paulo fail:
21035b9c547cSRui Paulo 	os_free(bias);
21045b9c547cSRui Paulo 	return -1;
21055b9c547cSRui Paulo }
21065b9c547cSRui Paulo #endif /* CONFIG_ACS */
21075b9c547cSRui Paulo 
21085b9c547cSRui Paulo 
parse_wpabuf_hex(int line,const char * name,struct wpabuf ** buf,const char * val)2109780fb4a2SCy Schubert static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf,
2110780fb4a2SCy Schubert 			    const char *val)
2111780fb4a2SCy Schubert {
2112780fb4a2SCy Schubert 	struct wpabuf *elems;
2113780fb4a2SCy Schubert 
2114780fb4a2SCy Schubert 	if (val[0] == '\0') {
2115780fb4a2SCy Schubert 		wpabuf_free(*buf);
2116780fb4a2SCy Schubert 		*buf = NULL;
2117780fb4a2SCy Schubert 		return 0;
2118780fb4a2SCy Schubert 	}
2119780fb4a2SCy Schubert 
2120780fb4a2SCy Schubert 	elems = wpabuf_parse_bin(val);
2121780fb4a2SCy Schubert 	if (!elems) {
2122780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
2123780fb4a2SCy Schubert 			   line, name, val);
2124780fb4a2SCy Schubert 		return -1;
2125780fb4a2SCy Schubert 	}
2126780fb4a2SCy Schubert 
2127780fb4a2SCy Schubert 	wpabuf_free(*buf);
2128780fb4a2SCy Schubert 	*buf = elems;
2129780fb4a2SCy Schubert 
2130780fb4a2SCy Schubert 	return 0;
2131780fb4a2SCy Schubert }
2132780fb4a2SCy Schubert 
2133780fb4a2SCy Schubert 
213485732ac8SCy Schubert #ifdef CONFIG_FILS
parse_fils_realm(struct hostapd_bss_config * bss,const char * val)213585732ac8SCy Schubert static int parse_fils_realm(struct hostapd_bss_config *bss, const char *val)
213685732ac8SCy Schubert {
213785732ac8SCy Schubert 	struct fils_realm *realm;
213885732ac8SCy Schubert 	size_t len;
213985732ac8SCy Schubert 
214085732ac8SCy Schubert 	len = os_strlen(val);
214185732ac8SCy Schubert 	realm = os_zalloc(sizeof(*realm) + len + 1);
214285732ac8SCy Schubert 	if (!realm)
214385732ac8SCy Schubert 		return -1;
214485732ac8SCy Schubert 
214585732ac8SCy Schubert 	os_memcpy(realm->realm, val, len);
214685732ac8SCy Schubert 	if (fils_domain_name_hash(val, realm->hash) < 0) {
214785732ac8SCy Schubert 		os_free(realm);
214885732ac8SCy Schubert 		return -1;
214985732ac8SCy Schubert 	}
215085732ac8SCy Schubert 	dl_list_add_tail(&bss->fils_realms, &realm->list);
215185732ac8SCy Schubert 
215285732ac8SCy Schubert 	return 0;
215385732ac8SCy Schubert }
215485732ac8SCy Schubert #endif /* CONFIG_FILS */
215585732ac8SCy Schubert 
215685732ac8SCy Schubert 
215785732ac8SCy Schubert #ifdef EAP_SERVER
parse_tls_flags(const char * val)215885732ac8SCy Schubert static unsigned int parse_tls_flags(const char *val)
215985732ac8SCy Schubert {
216085732ac8SCy Schubert 	unsigned int flags = 0;
216185732ac8SCy Schubert 
216285732ac8SCy Schubert 	/* Disable TLS v1.3 by default for now to avoid interoperability issue.
216385732ac8SCy Schubert 	 * This can be enabled by default once the implementation has been fully
216485732ac8SCy Schubert 	 * completed and tested with other implementations. */
216585732ac8SCy Schubert 	flags |= TLS_CONN_DISABLE_TLSv1_3;
216685732ac8SCy Schubert 
216785732ac8SCy Schubert 	if (os_strstr(val, "[ALLOW-SIGN-RSA-MD5]"))
216885732ac8SCy Schubert 		flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5;
216985732ac8SCy Schubert 	if (os_strstr(val, "[DISABLE-TIME-CHECKS]"))
217085732ac8SCy Schubert 		flags |= TLS_CONN_DISABLE_TIME_CHECKS;
217185732ac8SCy Schubert 	if (os_strstr(val, "[DISABLE-TLSv1.0]"))
217285732ac8SCy Schubert 		flags |= TLS_CONN_DISABLE_TLSv1_0;
21734bc52338SCy Schubert 	if (os_strstr(val, "[ENABLE-TLSv1.0]"))
21744bc52338SCy Schubert 		flags |= TLS_CONN_ENABLE_TLSv1_0;
217585732ac8SCy Schubert 	if (os_strstr(val, "[DISABLE-TLSv1.1]"))
217685732ac8SCy Schubert 		flags |= TLS_CONN_DISABLE_TLSv1_1;
21774bc52338SCy Schubert 	if (os_strstr(val, "[ENABLE-TLSv1.1]"))
21784bc52338SCy Schubert 		flags |= TLS_CONN_ENABLE_TLSv1_1;
217985732ac8SCy Schubert 	if (os_strstr(val, "[DISABLE-TLSv1.2]"))
218085732ac8SCy Schubert 		flags |= TLS_CONN_DISABLE_TLSv1_2;
21814bc52338SCy Schubert 	if (os_strstr(val, "[ENABLE-TLSv1.2]"))
21824bc52338SCy Schubert 		flags |= TLS_CONN_ENABLE_TLSv1_2;
218385732ac8SCy Schubert 	if (os_strstr(val, "[DISABLE-TLSv1.3]"))
218485732ac8SCy Schubert 		flags |= TLS_CONN_DISABLE_TLSv1_3;
218585732ac8SCy Schubert 	if (os_strstr(val, "[ENABLE-TLSv1.3]"))
218685732ac8SCy Schubert 		flags &= ~TLS_CONN_DISABLE_TLSv1_3;
218785732ac8SCy Schubert 	if (os_strstr(val, "[SUITEB]"))
218885732ac8SCy Schubert 		flags |= TLS_CONN_SUITEB;
218985732ac8SCy Schubert 	if (os_strstr(val, "[SUITEB-NO-ECDH]"))
219085732ac8SCy Schubert 		flags |= TLS_CONN_SUITEB_NO_ECDH | TLS_CONN_SUITEB;
219185732ac8SCy Schubert 
219285732ac8SCy Schubert 	return flags;
219385732ac8SCy Schubert }
219485732ac8SCy Schubert #endif /* EAP_SERVER */
219585732ac8SCy Schubert 
219685732ac8SCy Schubert 
2197206b73d0SCy Schubert #ifdef CONFIG_AIRTIME_POLICY
add_airtime_weight(struct hostapd_bss_config * bss,char * value)2198206b73d0SCy Schubert static int add_airtime_weight(struct hostapd_bss_config *bss, char *value)
2199206b73d0SCy Schubert {
2200206b73d0SCy Schubert 	struct airtime_sta_weight *wt;
2201206b73d0SCy Schubert 	char *pos, *next;
2202206b73d0SCy Schubert 
2203206b73d0SCy Schubert 	wt = os_zalloc(sizeof(*wt));
2204206b73d0SCy Schubert 	if (!wt)
2205206b73d0SCy Schubert 		return -1;
2206206b73d0SCy Schubert 
2207206b73d0SCy Schubert 	/* 02:01:02:03:04:05 10 */
2208206b73d0SCy Schubert 	pos = value;
2209206b73d0SCy Schubert 	next = os_strchr(pos, ' ');
2210206b73d0SCy Schubert 	if (next)
2211206b73d0SCy Schubert 		*next++ = '\0';
2212206b73d0SCy Schubert 	if (!next || hwaddr_aton(pos, wt->addr)) {
2213206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "Invalid station address: '%s'", pos);
2214206b73d0SCy Schubert 		os_free(wt);
2215206b73d0SCy Schubert 		return -1;
2216206b73d0SCy Schubert 	}
2217206b73d0SCy Schubert 
2218206b73d0SCy Schubert 	pos = next;
2219206b73d0SCy Schubert 	wt->weight = atoi(pos);
2220206b73d0SCy Schubert 	if (!wt->weight) {
2221206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "Invalid weight: '%s'", pos);
2222206b73d0SCy Schubert 		os_free(wt);
2223206b73d0SCy Schubert 		return -1;
2224206b73d0SCy Schubert 	}
2225206b73d0SCy Schubert 
2226206b73d0SCy Schubert 	wt->next = bss->airtime_weight_list;
2227206b73d0SCy Schubert 	bss->airtime_weight_list = wt;
2228206b73d0SCy Schubert 	return 0;
2229206b73d0SCy Schubert }
2230206b73d0SCy Schubert #endif /* CONFIG_AIRTIME_POLICY */
2231206b73d0SCy Schubert 
2232206b73d0SCy Schubert 
223385732ac8SCy Schubert #ifdef CONFIG_SAE
2234*a90b9d01SCy Schubert 
parse_sae_password(struct hostapd_bss_config * bss,const char * val)223585732ac8SCy Schubert static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
223685732ac8SCy Schubert {
223785732ac8SCy Schubert 	struct sae_password_entry *pw;
223885732ac8SCy Schubert 	const char *pos = val, *pos2, *end = NULL;
223985732ac8SCy Schubert 
224085732ac8SCy Schubert 	pw = os_zalloc(sizeof(*pw));
224185732ac8SCy Schubert 	if (!pw)
224285732ac8SCy Schubert 		return -1;
224385732ac8SCy Schubert 	os_memset(pw->peer_addr, 0xff, ETH_ALEN); /* default to wildcard */
224485732ac8SCy Schubert 
224585732ac8SCy Schubert 	pos2 = os_strstr(pos, "|mac=");
224685732ac8SCy Schubert 	if (pos2) {
224785732ac8SCy Schubert 		end = pos2;
224885732ac8SCy Schubert 		pos2 += 5;
224985732ac8SCy Schubert 		if (hwaddr_aton(pos2, pw->peer_addr) < 0)
225085732ac8SCy Schubert 			goto fail;
225185732ac8SCy Schubert 		pos = pos2 + ETH_ALEN * 3 - 1;
225285732ac8SCy Schubert 	}
225385732ac8SCy Schubert 
22544bc52338SCy Schubert 	pos2 = os_strstr(pos, "|vlanid=");
22554bc52338SCy Schubert 	if (pos2) {
22564bc52338SCy Schubert 		if (!end)
22574bc52338SCy Schubert 			end = pos2;
22584bc52338SCy Schubert 		pos2 += 8;
22594bc52338SCy Schubert 		pw->vlan_id = atoi(pos2);
22604bc52338SCy Schubert 	}
22614bc52338SCy Schubert 
2262c1d255d3SCy Schubert #ifdef CONFIG_SAE_PK
2263c1d255d3SCy Schubert 	pos2 = os_strstr(pos, "|pk=");
2264c1d255d3SCy Schubert 	if (pos2) {
2265c1d255d3SCy Schubert 		const char *epos;
2266c1d255d3SCy Schubert 		char *tmp;
2267c1d255d3SCy Schubert 
2268c1d255d3SCy Schubert 		if (!end)
2269c1d255d3SCy Schubert 			end = pos2;
2270c1d255d3SCy Schubert 		pos2 += 4;
2271c1d255d3SCy Schubert 		epos = os_strchr(pos2, '|');
2272c1d255d3SCy Schubert 		if (epos) {
2273c1d255d3SCy Schubert 			tmp = os_malloc(epos - pos2 + 1);
2274c1d255d3SCy Schubert 			if (!tmp)
2275c1d255d3SCy Schubert 				goto fail;
2276c1d255d3SCy Schubert 			os_memcpy(tmp, pos2, epos - pos2);
2277c1d255d3SCy Schubert 			tmp[epos - pos2] = '\0';
2278c1d255d3SCy Schubert 		} else {
2279c1d255d3SCy Schubert 			tmp = os_strdup(pos2);
2280c1d255d3SCy Schubert 			if (!tmp)
2281c1d255d3SCy Schubert 				goto fail;
2282c1d255d3SCy Schubert 		}
2283c1d255d3SCy Schubert 
2284c1d255d3SCy Schubert 		pw->pk = sae_parse_pk(tmp);
2285c1d255d3SCy Schubert 		str_clear_free(tmp);
2286c1d255d3SCy Schubert 		if (!pw->pk)
2287c1d255d3SCy Schubert 			goto fail;
2288c1d255d3SCy Schubert 	}
2289c1d255d3SCy Schubert #endif /* CONFIG_SAE_PK */
2290c1d255d3SCy Schubert 
229185732ac8SCy Schubert 	pos2 = os_strstr(pos, "|id=");
229285732ac8SCy Schubert 	if (pos2) {
229385732ac8SCy Schubert 		if (!end)
229485732ac8SCy Schubert 			end = pos2;
229585732ac8SCy Schubert 		pos2 += 4;
229685732ac8SCy Schubert 		pw->identifier = os_strdup(pos2);
229785732ac8SCy Schubert 		if (!pw->identifier)
229885732ac8SCy Schubert 			goto fail;
229985732ac8SCy Schubert 	}
230085732ac8SCy Schubert 
230185732ac8SCy Schubert 	if (!end) {
230285732ac8SCy Schubert 		pw->password = os_strdup(val);
230385732ac8SCy Schubert 		if (!pw->password)
230485732ac8SCy Schubert 			goto fail;
230585732ac8SCy Schubert 	} else {
230685732ac8SCy Schubert 		pw->password = os_malloc(end - val + 1);
230785732ac8SCy Schubert 		if (!pw->password)
230885732ac8SCy Schubert 			goto fail;
230985732ac8SCy Schubert 		os_memcpy(pw->password, val, end - val);
231085732ac8SCy Schubert 		pw->password[end - val] = '\0';
231185732ac8SCy Schubert 	}
231285732ac8SCy Schubert 
2313c1d255d3SCy Schubert #ifdef CONFIG_SAE_PK
2314c1d255d3SCy Schubert 	if (pw->pk &&
2315c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
2316c1d255d3SCy Schubert 	    !bss->sae_pk_password_check_skip &&
2317c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
2318c1d255d3SCy Schubert 	    !sae_pk_valid_password(pw->password)) {
2319c1d255d3SCy Schubert 		wpa_printf(MSG_INFO,
2320c1d255d3SCy Schubert 			   "Invalid SAE password for a SAE-PK sae_password entry");
2321c1d255d3SCy Schubert 		goto fail;
2322c1d255d3SCy Schubert 	}
2323c1d255d3SCy Schubert #endif /* CONFIG_SAE_PK */
2324c1d255d3SCy Schubert 
232585732ac8SCy Schubert 	pw->next = bss->sae_passwords;
232685732ac8SCy Schubert 	bss->sae_passwords = pw;
232785732ac8SCy Schubert 
232885732ac8SCy Schubert 	return 0;
232985732ac8SCy Schubert fail:
233085732ac8SCy Schubert 	str_clear_free(pw->password);
233185732ac8SCy Schubert 	os_free(pw->identifier);
2332c1d255d3SCy Schubert #ifdef CONFIG_SAE_PK
2333c1d255d3SCy Schubert 	sae_deinit_pk(pw->pk);
2334c1d255d3SCy Schubert #endif /* CONFIG_SAE_PK */
233585732ac8SCy Schubert 	os_free(pw);
233685732ac8SCy Schubert 	return -1;
233785732ac8SCy Schubert }
2338*a90b9d01SCy Schubert 
2339*a90b9d01SCy Schubert 
parse_sae_password_file(struct hostapd_bss_config * bss,const char * fname)2340*a90b9d01SCy Schubert static int parse_sae_password_file(struct hostapd_bss_config *bss,
2341*a90b9d01SCy Schubert 				   const char *fname)
2342*a90b9d01SCy Schubert {
2343*a90b9d01SCy Schubert 	FILE *f;
2344*a90b9d01SCy Schubert 	char buf[500], *pos;
2345*a90b9d01SCy Schubert 	unsigned int line = 0;
2346*a90b9d01SCy Schubert 
2347*a90b9d01SCy Schubert 	f = fopen(fname, "r");
2348*a90b9d01SCy Schubert 	if (!f) {
2349*a90b9d01SCy Schubert 		wpa_printf(MSG_ERROR, "sae_password_file '%s' not found.",
2350*a90b9d01SCy Schubert 			   fname);
2351*a90b9d01SCy Schubert 		return -1;
2352*a90b9d01SCy Schubert 	}
2353*a90b9d01SCy Schubert 
2354*a90b9d01SCy Schubert 	while (fgets(buf, sizeof(buf), f)) {
2355*a90b9d01SCy Schubert 		pos = os_strchr(buf, '\n');
2356*a90b9d01SCy Schubert 		if (pos)
2357*a90b9d01SCy Schubert 			*pos = '\0';
2358*a90b9d01SCy Schubert 		line++;
2359*a90b9d01SCy Schubert 		if (parse_sae_password(bss, buf)) {
2360*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
2361*a90b9d01SCy Schubert 				   "Invalid SAE password at line %d in '%s'",
2362*a90b9d01SCy Schubert 				   line, fname);
2363*a90b9d01SCy Schubert 			fclose(f);
2364*a90b9d01SCy Schubert 			return -1;
2365*a90b9d01SCy Schubert 		}
2366*a90b9d01SCy Schubert 	}
2367*a90b9d01SCy Schubert 
2368*a90b9d01SCy Schubert 	fclose(f);
2369*a90b9d01SCy Schubert 	return 0;
2370*a90b9d01SCy Schubert }
2371*a90b9d01SCy Schubert 
237285732ac8SCy Schubert #endif /* CONFIG_SAE */
237385732ac8SCy Schubert 
237485732ac8SCy Schubert 
2375206b73d0SCy Schubert #ifdef CONFIG_DPP2
hostapd_dpp_controller_parse(struct hostapd_bss_config * bss,const char * pos)2376206b73d0SCy Schubert static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss,
2377206b73d0SCy Schubert 					const char *pos)
2378206b73d0SCy Schubert {
2379206b73d0SCy Schubert 	struct dpp_controller_conf *conf;
2380206b73d0SCy Schubert 	char *val;
2381206b73d0SCy Schubert 
2382206b73d0SCy Schubert 	conf = os_zalloc(sizeof(*conf));
2383206b73d0SCy Schubert 	if (!conf)
2384206b73d0SCy Schubert 		return -1;
2385206b73d0SCy Schubert 	val = get_param(pos, "ipaddr=");
2386206b73d0SCy Schubert 	if (!val || hostapd_parse_ip_addr(val, &conf->ipaddr))
2387206b73d0SCy Schubert 		goto fail;
2388206b73d0SCy Schubert 	os_free(val);
2389206b73d0SCy Schubert 	val = get_param(pos, "pkhash=");
2390206b73d0SCy Schubert 	if (!val || os_strlen(val) != 2 * SHA256_MAC_LEN ||
2391206b73d0SCy Schubert 	    hexstr2bin(val, conf->pkhash, SHA256_MAC_LEN) < 0)
2392206b73d0SCy Schubert 		goto fail;
2393206b73d0SCy Schubert 	os_free(val);
2394206b73d0SCy Schubert 	conf->next = bss->dpp_controller;
2395206b73d0SCy Schubert 	bss->dpp_controller = conf;
2396206b73d0SCy Schubert 	return 0;
2397206b73d0SCy Schubert fail:
2398206b73d0SCy Schubert 	os_free(val);
2399206b73d0SCy Schubert 	os_free(conf);
2400206b73d0SCy Schubert 	return -1;
2401206b73d0SCy Schubert }
2402206b73d0SCy Schubert #endif /* CONFIG_DPP2 */
2403206b73d0SCy Schubert 
2404206b73d0SCy Schubert 
get_hex_config(u8 * buf,size_t max_len,int line,const char * field,const char * val)2405c1d255d3SCy Schubert static int get_hex_config(u8 *buf, size_t max_len, int line,
2406c1d255d3SCy Schubert 			  const char *field, const char *val)
2407c1d255d3SCy Schubert {
2408c1d255d3SCy Schubert 	size_t hlen = os_strlen(val), len = hlen / 2;
2409c1d255d3SCy Schubert 	u8 tmp[EXT_CAPA_MAX_LEN];
2410c1d255d3SCy Schubert 
2411c1d255d3SCy Schubert 	os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
2412c1d255d3SCy Schubert 	if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
2413c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
2414c1d255d3SCy Schubert 		return -1;
2415c1d255d3SCy Schubert 	}
2416c1d255d3SCy Schubert 	os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
2417c1d255d3SCy Schubert 	return 0;
2418c1d255d3SCy Schubert }
2419c1d255d3SCy Schubert 
2420c1d255d3SCy Schubert 
2421*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE
get_u16(const char * pos,int line,u16 * ret_val)2422*a90b9d01SCy Schubert static int get_u16(const char *pos, int line, u16 *ret_val)
2423*a90b9d01SCy Schubert {
2424*a90b9d01SCy Schubert 	char *end;
2425*a90b9d01SCy Schubert 	long int val = strtol(pos, &end, 0);
2426*a90b9d01SCy Schubert 
2427*a90b9d01SCy Schubert 	if (*end || val < 0 || val > 0xffff) {
2428*a90b9d01SCy Schubert 		wpa_printf(MSG_ERROR, "Line %d: Invalid value '%s'",
2429*a90b9d01SCy Schubert 			   line, pos);
2430*a90b9d01SCy Schubert 		return -1;
2431*a90b9d01SCy Schubert 	}
2432*a90b9d01SCy Schubert 
2433*a90b9d01SCy Schubert 	*ret_val = val;
2434*a90b9d01SCy Schubert 	return 0;
2435*a90b9d01SCy Schubert }
2436*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */
2437*a90b9d01SCy Schubert 
2438*a90b9d01SCy Schubert 
hostapd_config_fill(struct hostapd_config * conf,struct hostapd_bss_config * bss,const char * buf,char * pos,int line)2439f05cddf9SRui Paulo static int hostapd_config_fill(struct hostapd_config *conf,
2440f05cddf9SRui Paulo 			       struct hostapd_bss_config *bss,
2441325151a3SRui Paulo 			       const char *buf, char *pos, int line)
2442f05cddf9SRui Paulo {
2443e28a4053SRui Paulo 	if (os_strcmp(buf, "interface") == 0) {
24445b9c547cSRui Paulo 		os_strlcpy(conf->bss[0]->iface, pos,
24455b9c547cSRui Paulo 			   sizeof(conf->bss[0]->iface));
2446e28a4053SRui Paulo 	} else if (os_strcmp(buf, "bridge") == 0) {
2447e28a4053SRui Paulo 		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
2448*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "bridge_hairpin") == 0) {
2449*a90b9d01SCy Schubert 		bss->bridge_hairpin = atoi(pos);
24505b9c547cSRui Paulo 	} else if (os_strcmp(buf, "vlan_bridge") == 0) {
24515b9c547cSRui Paulo 		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
2452f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wds_bridge") == 0) {
24535b9c547cSRui Paulo 		os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
2454e28a4053SRui Paulo 	} else if (os_strcmp(buf, "driver") == 0) {
2455e28a4053SRui Paulo 		int j;
245685732ac8SCy Schubert 		const struct wpa_driver_ops *driver = NULL;
245785732ac8SCy Schubert 
2458e28a4053SRui Paulo 		for (j = 0; wpa_drivers[j]; j++) {
24595b9c547cSRui Paulo 			if (os_strcmp(pos, wpa_drivers[j]->name) == 0) {
246085732ac8SCy Schubert 				driver = wpa_drivers[j];
2461e28a4053SRui Paulo 				break;
2462e28a4053SRui Paulo 			}
2463e28a4053SRui Paulo 		}
246485732ac8SCy Schubert 		if (!driver) {
24655b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
24665b9c547cSRui Paulo 				   "Line %d: invalid/unknown driver '%s'",
24675b9c547cSRui Paulo 				   line, pos);
24685b9c547cSRui Paulo 			return 1;
2469e28a4053SRui Paulo 		}
247085732ac8SCy Schubert 		conf->driver = driver;
24715b9c547cSRui Paulo 	} else if (os_strcmp(buf, "driver_params") == 0) {
24725b9c547cSRui Paulo 		os_free(conf->driver_params);
24735b9c547cSRui Paulo 		conf->driver_params = os_strdup(pos);
2474e28a4053SRui Paulo 	} else if (os_strcmp(buf, "debug") == 0) {
24755b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore",
24765b9c547cSRui Paulo 			   line);
2477e28a4053SRui Paulo 	} else if (os_strcmp(buf, "logger_syslog_level") == 0) {
2478e28a4053SRui Paulo 		bss->logger_syslog_level = atoi(pos);
2479e28a4053SRui Paulo 	} else if (os_strcmp(buf, "logger_stdout_level") == 0) {
2480e28a4053SRui Paulo 		bss->logger_stdout_level = atoi(pos);
2481e28a4053SRui Paulo 	} else if (os_strcmp(buf, "logger_syslog") == 0) {
2482e28a4053SRui Paulo 		bss->logger_syslog = atoi(pos);
2483e28a4053SRui Paulo 	} else if (os_strcmp(buf, "logger_stdout") == 0) {
2484e28a4053SRui Paulo 		bss->logger_stdout = atoi(pos);
2485e28a4053SRui Paulo 	} else if (os_strcmp(buf, "dump_file") == 0) {
24865b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
24875b9c547cSRui Paulo 			   line);
2488e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ssid") == 0) {
24894b72b91aSCy Schubert 		struct hostapd_ssid *ssid = &bss->ssid;
24904b72b91aSCy Schubert 
24914b72b91aSCy Schubert 		ssid->ssid_len = os_strlen(pos);
24924b72b91aSCy Schubert 		if (ssid->ssid_len > SSID_MAX_LEN || ssid->ssid_len < 1) {
24935b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
24945b9c547cSRui Paulo 				   line, pos);
24955b9c547cSRui Paulo 			return 1;
2496e28a4053SRui Paulo 		}
24974b72b91aSCy Schubert 		os_memcpy(ssid->ssid, pos, ssid->ssid_len);
24984b72b91aSCy Schubert 		ssid->ssid_set = 1;
2499*a90b9d01SCy Schubert 		ssid->short_ssid = ieee80211_crc32(ssid->ssid, ssid->ssid_len);
2500f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "ssid2") == 0) {
25014b72b91aSCy Schubert 		struct hostapd_ssid *ssid = &bss->ssid;
2502f05cddf9SRui Paulo 		size_t slen;
2503f05cddf9SRui Paulo 		char *str = wpa_config_parse_string(pos, &slen);
2504325151a3SRui Paulo 		if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
25055b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
25065b9c547cSRui Paulo 				   line, pos);
25075b9c547cSRui Paulo 			os_free(str);
25085b9c547cSRui Paulo 			return 1;
25095b9c547cSRui Paulo 		}
25104b72b91aSCy Schubert 		os_memcpy(ssid->ssid, str, slen);
25114b72b91aSCy Schubert 		ssid->ssid_len = slen;
25124b72b91aSCy Schubert 		ssid->ssid_set = 1;
2513*a90b9d01SCy Schubert 		ssid->short_ssid = ieee80211_crc32(ssid->ssid, ssid->ssid_len);
2514f05cddf9SRui Paulo 		os_free(str);
2515f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "utf8_ssid") == 0) {
2516f05cddf9SRui Paulo 		bss->ssid.utf8_ssid = atoi(pos) > 0;
2517e28a4053SRui Paulo 	} else if (os_strcmp(buf, "macaddr_acl") == 0) {
251885732ac8SCy Schubert 		enum macaddr_acl acl = atoi(pos);
251985732ac8SCy Schubert 
252085732ac8SCy Schubert 		if (acl != ACCEPT_UNLESS_DENIED &&
252185732ac8SCy Schubert 		    acl != DENY_UNLESS_ACCEPTED &&
252285732ac8SCy Schubert 		    acl != USE_EXTERNAL_RADIUS_AUTH) {
25235b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d",
252485732ac8SCy Schubert 				   line, acl);
252585732ac8SCy Schubert 			return 1;
2526e28a4053SRui Paulo 		}
252785732ac8SCy Schubert 		bss->macaddr_acl = acl;
2528e28a4053SRui Paulo 	} else if (os_strcmp(buf, "accept_mac_file") == 0) {
2529e28a4053SRui Paulo 		if (hostapd_config_read_maclist(pos, &bss->accept_mac,
25305b9c547cSRui Paulo 						&bss->num_accept_mac)) {
25315b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'",
2532e28a4053SRui Paulo 				   line, pos);
25335b9c547cSRui Paulo 			return 1;
2534e28a4053SRui Paulo 		}
2535e28a4053SRui Paulo 	} else if (os_strcmp(buf, "deny_mac_file") == 0) {
2536e28a4053SRui Paulo 		if (hostapd_config_read_maclist(pos, &bss->deny_mac,
2537e28a4053SRui Paulo 						&bss->num_deny_mac)) {
25385b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'",
2539e28a4053SRui Paulo 				   line, pos);
25405b9c547cSRui Paulo 			return 1;
2541e28a4053SRui Paulo 		}
2542e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wds_sta") == 0) {
2543e28a4053SRui Paulo 		bss->wds_sta = atoi(pos);
25445b9c547cSRui Paulo 	} else if (os_strcmp(buf, "start_disabled") == 0) {
25455b9c547cSRui Paulo 		bss->start_disabled = atoi(pos);
2546f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "ap_isolate") == 0) {
2547f05cddf9SRui Paulo 		bss->isolate = atoi(pos);
2548e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
2549e28a4053SRui Paulo 		bss->ap_max_inactivity = atoi(pos);
2550f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
2551f05cddf9SRui Paulo 		bss->skip_inactivity_poll = atoi(pos);
2552*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "bss_max_idle") == 0) {
2553*a90b9d01SCy Schubert 		int val = atoi(pos);
2554*a90b9d01SCy Schubert 
2555*a90b9d01SCy Schubert 		if (val < 0 || val > 2) {
2556*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
2557*a90b9d01SCy Schubert 				   "Line %d: Invalid bss_max_idle value", line);
2558*a90b9d01SCy Schubert 			return 1;
2559*a90b9d01SCy Schubert 		}
2560*a90b9d01SCy Schubert 		bss->bss_max_idle = val;
2561*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "max_acceptable_idle_period") == 0) {
2562*a90b9d01SCy Schubert 		bss->max_acceptable_idle_period = atoi(pos);
2563*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "no_disconnect_on_group_keyerror") == 0) {
2564*a90b9d01SCy Schubert 		int val = atoi(pos);
2565*a90b9d01SCy Schubert 
2566*a90b9d01SCy Schubert 		if (val < 0 || val > 1) {
2567*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
2568*a90b9d01SCy Schubert 				   "Line %d: Invalid no_disconnect_on_group_keyerror",
2569*a90b9d01SCy Schubert 				   line);
2570*a90b9d01SCy Schubert 			return 1;
2571*a90b9d01SCy Schubert 		}
2572*a90b9d01SCy Schubert 		bss->no_disconnect_on_group_keyerror = val;
2573*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "config_id") == 0) {
2574*a90b9d01SCy Schubert 		os_free(bss->config_id);
2575*a90b9d01SCy Schubert 		bss->config_id = os_strdup(pos);
2576e28a4053SRui Paulo 	} else if (os_strcmp(buf, "country_code") == 0) {
2577c1d255d3SCy Schubert 		if (pos[0] < 'A' || pos[0] > 'Z' ||
2578c1d255d3SCy Schubert 		    pos[1] < 'A' || pos[1] > 'Z') {
2579c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
2580c1d255d3SCy Schubert 				   "Line %d: Invalid country_code '%s'",
2581c1d255d3SCy Schubert 				   line, pos);
2582c1d255d3SCy Schubert 			return 1;
2583c1d255d3SCy Schubert 		}
2584e28a4053SRui Paulo 		os_memcpy(conf->country, pos, 2);
258585732ac8SCy Schubert 	} else if (os_strcmp(buf, "country3") == 0) {
258685732ac8SCy Schubert 		conf->country[2] = strtol(pos, NULL, 16);
2587e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ieee80211d") == 0) {
2588e28a4053SRui Paulo 		conf->ieee80211d = atoi(pos);
25895b9c547cSRui Paulo 	} else if (os_strcmp(buf, "ieee80211h") == 0) {
25905b9c547cSRui Paulo 		conf->ieee80211h = atoi(pos);
2591e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ieee8021x") == 0) {
2592e28a4053SRui Paulo 		bss->ieee802_1x = atoi(pos);
2593e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eapol_version") == 0) {
259485732ac8SCy Schubert 		int eapol_version = atoi(pos);
2595206b73d0SCy Schubert #ifdef CONFIG_MACSEC
2596c1d255d3SCy Schubert 		int max_ver = 3;
2597206b73d0SCy Schubert #else /* CONFIG_MACSEC */
2598c1d255d3SCy Schubert 		int max_ver = 2;
2599206b73d0SCy Schubert #endif /* CONFIG_MACSEC */
2600c1d255d3SCy Schubert 
2601c1d255d3SCy Schubert 		if (eapol_version < 1 || eapol_version > max_ver) {
26025b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
26035b9c547cSRui Paulo 				   "Line %d: invalid EAPOL version (%d): '%s'.",
260485732ac8SCy Schubert 				   line, eapol_version, pos);
26055b9c547cSRui Paulo 			return 1;
26065b9c547cSRui Paulo 		}
260785732ac8SCy Schubert 		bss->eapol_version = eapol_version;
26085b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version);
2609e28a4053SRui Paulo #ifdef EAP_SERVER
2610e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_authenticator") == 0) {
2611e28a4053SRui Paulo 		bss->eap_server = atoi(pos);
26125b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line);
2613e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_server") == 0) {
2614e28a4053SRui Paulo 		bss->eap_server = atoi(pos);
2615e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_user_file") == 0) {
2616e28a4053SRui Paulo 		if (hostapd_config_read_eap_user(pos, bss))
26175b9c547cSRui Paulo 			return 1;
2618e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ca_cert") == 0) {
2619e28a4053SRui Paulo 		os_free(bss->ca_cert);
2620e28a4053SRui Paulo 		bss->ca_cert = os_strdup(pos);
2621e28a4053SRui Paulo 	} else if (os_strcmp(buf, "server_cert") == 0) {
2622e28a4053SRui Paulo 		os_free(bss->server_cert);
2623e28a4053SRui Paulo 		bss->server_cert = os_strdup(pos);
2624206b73d0SCy Schubert 	} else if (os_strcmp(buf, "server_cert2") == 0) {
2625206b73d0SCy Schubert 		os_free(bss->server_cert2);
2626206b73d0SCy Schubert 		bss->server_cert2 = os_strdup(pos);
2627e28a4053SRui Paulo 	} else if (os_strcmp(buf, "private_key") == 0) {
2628e28a4053SRui Paulo 		os_free(bss->private_key);
2629e28a4053SRui Paulo 		bss->private_key = os_strdup(pos);
2630206b73d0SCy Schubert 	} else if (os_strcmp(buf, "private_key2") == 0) {
2631206b73d0SCy Schubert 		os_free(bss->private_key2);
2632206b73d0SCy Schubert 		bss->private_key2 = os_strdup(pos);
2633e28a4053SRui Paulo 	} else if (os_strcmp(buf, "private_key_passwd") == 0) {
2634e28a4053SRui Paulo 		os_free(bss->private_key_passwd);
2635e28a4053SRui Paulo 		bss->private_key_passwd = os_strdup(pos);
2636206b73d0SCy Schubert 	} else if (os_strcmp(buf, "private_key_passwd2") == 0) {
2637206b73d0SCy Schubert 		os_free(bss->private_key_passwd2);
2638206b73d0SCy Schubert 		bss->private_key_passwd2 = os_strdup(pos);
26394bc52338SCy Schubert 	} else if (os_strcmp(buf, "check_cert_subject") == 0) {
26404bc52338SCy Schubert 		if (!pos[0]) {
26414bc52338SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'",
26424bc52338SCy Schubert 				   line, pos);
26434bc52338SCy Schubert 			return 1;
26444bc52338SCy Schubert 		}
26454bc52338SCy Schubert 		os_free(bss->check_cert_subject);
26464bc52338SCy Schubert 		bss->check_cert_subject = os_strdup(pos);
26474bc52338SCy Schubert 		if (!bss->check_cert_subject)
26484bc52338SCy Schubert 			return 1;
2649e28a4053SRui Paulo 	} else if (os_strcmp(buf, "check_crl") == 0) {
2650e28a4053SRui Paulo 		bss->check_crl = atoi(pos);
26514bc52338SCy Schubert 	} else if (os_strcmp(buf, "check_crl_strict") == 0) {
26524bc52338SCy Schubert 		bss->check_crl_strict = atoi(pos);
26534bc52338SCy Schubert 	} else if (os_strcmp(buf, "crl_reload_interval") == 0) {
26544bc52338SCy Schubert 		bss->crl_reload_interval = atoi(pos);
2655325151a3SRui Paulo 	} else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
2656325151a3SRui Paulo 		bss->tls_session_lifetime = atoi(pos);
265785732ac8SCy Schubert 	} else if (os_strcmp(buf, "tls_flags") == 0) {
265885732ac8SCy Schubert 		bss->tls_flags = parse_tls_flags(pos);
2659c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "max_auth_rounds") == 0) {
2660c1d255d3SCy Schubert 		bss->max_auth_rounds = atoi(pos);
2661c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "max_auth_rounds_short") == 0) {
2662c1d255d3SCy Schubert 		bss->max_auth_rounds_short = atoi(pos);
26635b9c547cSRui Paulo 	} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
26645b9c547cSRui Paulo 		os_free(bss->ocsp_stapling_response);
26655b9c547cSRui Paulo 		bss->ocsp_stapling_response = os_strdup(pos);
2666780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) {
2667780fb4a2SCy Schubert 		os_free(bss->ocsp_stapling_response_multi);
2668780fb4a2SCy Schubert 		bss->ocsp_stapling_response_multi = os_strdup(pos);
2669e28a4053SRui Paulo 	} else if (os_strcmp(buf, "dh_file") == 0) {
2670e28a4053SRui Paulo 		os_free(bss->dh_file);
2671e28a4053SRui Paulo 		bss->dh_file = os_strdup(pos);
26725b9c547cSRui Paulo 	} else if (os_strcmp(buf, "openssl_ciphers") == 0) {
26735b9c547cSRui Paulo 		os_free(bss->openssl_ciphers);
26745b9c547cSRui Paulo 		bss->openssl_ciphers = os_strdup(pos);
26754bc52338SCy Schubert 	} else if (os_strcmp(buf, "openssl_ecdh_curves") == 0) {
26764bc52338SCy Schubert 		os_free(bss->openssl_ecdh_curves);
26774bc52338SCy Schubert 		bss->openssl_ecdh_curves = os_strdup(pos);
2678f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "fragment_size") == 0) {
2679f05cddf9SRui Paulo 		bss->fragment_size = atoi(pos);
2680e28a4053SRui Paulo #ifdef EAP_SERVER_FAST
2681e28a4053SRui Paulo 	} else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
2682e28a4053SRui Paulo 		os_free(bss->pac_opaque_encr_key);
2683e28a4053SRui Paulo 		bss->pac_opaque_encr_key = os_malloc(16);
2684e28a4053SRui Paulo 		if (bss->pac_opaque_encr_key == NULL) {
26855b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
26865b9c547cSRui Paulo 				   "Line %d: No memory for pac_opaque_encr_key",
26875b9c547cSRui Paulo 				   line);
26885b9c547cSRui Paulo 			return 1;
26895b9c547cSRui Paulo 		} else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) {
26905b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key",
26915b9c547cSRui Paulo 				   line);
26925b9c547cSRui Paulo 			return 1;
2693e28a4053SRui Paulo 		}
2694e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
2695e28a4053SRui Paulo 		size_t idlen = os_strlen(pos);
2696e28a4053SRui Paulo 		if (idlen & 1) {
26975b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id",
26985b9c547cSRui Paulo 				   line);
26995b9c547cSRui Paulo 			return 1;
27005b9c547cSRui Paulo 		}
2701e28a4053SRui Paulo 		os_free(bss->eap_fast_a_id);
2702e28a4053SRui Paulo 		bss->eap_fast_a_id = os_malloc(idlen / 2);
2703e28a4053SRui Paulo 		if (bss->eap_fast_a_id == NULL ||
27045b9c547cSRui Paulo 		    hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) {
27055b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id",
27065b9c547cSRui Paulo 				   line);
27075b9c547cSRui Paulo 			os_free(bss->eap_fast_a_id);
27085b9c547cSRui Paulo 			bss->eap_fast_a_id = NULL;
27095b9c547cSRui Paulo 			return 1;
27105b9c547cSRui Paulo 		} else {
2711e28a4053SRui Paulo 			bss->eap_fast_a_id_len = idlen / 2;
2712e28a4053SRui Paulo 		}
2713e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
2714e28a4053SRui Paulo 		os_free(bss->eap_fast_a_id_info);
2715e28a4053SRui Paulo 		bss->eap_fast_a_id_info = os_strdup(pos);
2716e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_fast_prov") == 0) {
2717e28a4053SRui Paulo 		bss->eap_fast_prov = atoi(pos);
2718e28a4053SRui Paulo 	} else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
2719e28a4053SRui Paulo 		bss->pac_key_lifetime = atoi(pos);
2720e28a4053SRui Paulo 	} else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
2721e28a4053SRui Paulo 		bss->pac_key_refresh_time = atoi(pos);
2722e28a4053SRui Paulo #endif /* EAP_SERVER_FAST */
2723206b73d0SCy Schubert #ifdef EAP_SERVER_TEAP
2724206b73d0SCy Schubert 	} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
2725206b73d0SCy Schubert 		int val = atoi(pos);
2726206b73d0SCy Schubert 
2727c1d255d3SCy Schubert 		if (val < 0 || val > 2) {
2728206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
2729206b73d0SCy Schubert 				   "Line %d: Invalid eap_teap_auth value",
2730206b73d0SCy Schubert 				   line);
2731206b73d0SCy Schubert 			return 1;
2732206b73d0SCy Schubert 		}
2733206b73d0SCy Schubert 		bss->eap_teap_auth = val;
2734206b73d0SCy Schubert 	} else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) {
2735206b73d0SCy Schubert 		bss->eap_teap_pac_no_inner = atoi(pos);
2736c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
2737c1d255d3SCy Schubert 		bss->eap_teap_separate_result = atoi(pos);
2738c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "eap_teap_id") == 0) {
2739c1d255d3SCy Schubert 		bss->eap_teap_id = atoi(pos);
2740*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eap_teap_method_sequence") == 0) {
2741*a90b9d01SCy Schubert 		bss->eap_teap_method_sequence = atoi(pos);
2742206b73d0SCy Schubert #endif /* EAP_SERVER_TEAP */
2743e28a4053SRui Paulo #ifdef EAP_SERVER_SIM
2744e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_sim_db") == 0) {
2745e28a4053SRui Paulo 		os_free(bss->eap_sim_db);
2746e28a4053SRui Paulo 		bss->eap_sim_db = os_strdup(pos);
2747780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) {
2748780fb4a2SCy Schubert 		bss->eap_sim_db_timeout = atoi(pos);
2749e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
2750e28a4053SRui Paulo 		bss->eap_sim_aka_result_ind = atoi(pos);
2751206b73d0SCy Schubert 	} else if (os_strcmp(buf, "eap_sim_id") == 0) {
2752206b73d0SCy Schubert 		bss->eap_sim_id = atoi(pos);
2753*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "imsi_privacy_key") == 0) {
2754*a90b9d01SCy Schubert 		os_free(bss->imsi_privacy_key);
2755*a90b9d01SCy Schubert 		bss->imsi_privacy_key = os_strdup(pos);
2756*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eap_sim_aka_fast_reauth_limit") == 0) {
2757*a90b9d01SCy Schubert 		bss->eap_sim_aka_fast_reauth_limit = atoi(pos);
2758e28a4053SRui Paulo #endif /* EAP_SERVER_SIM */
2759e28a4053SRui Paulo #ifdef EAP_SERVER_TNC
2760e28a4053SRui Paulo 	} else if (os_strcmp(buf, "tnc") == 0) {
2761e28a4053SRui Paulo 		bss->tnc = atoi(pos);
2762e28a4053SRui Paulo #endif /* EAP_SERVER_TNC */
2763f05cddf9SRui Paulo #ifdef EAP_SERVER_PWD
2764f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "pwd_group") == 0) {
2765f05cddf9SRui Paulo 		bss->pwd_group = atoi(pos);
2766f05cddf9SRui Paulo #endif /* EAP_SERVER_PWD */
276785732ac8SCy Schubert #ifdef CONFIG_ERP
27685b9c547cSRui Paulo 	} else if (os_strcmp(buf, "eap_server_erp") == 0) {
27695b9c547cSRui Paulo 		bss->eap_server_erp = atoi(pos);
277085732ac8SCy Schubert #endif /* CONFIG_ERP */
2771e28a4053SRui Paulo #endif /* EAP_SERVER */
2772e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_message") == 0) {
2773e28a4053SRui Paulo 		char *term;
27745b9c547cSRui Paulo 		os_free(bss->eap_req_id_text);
2775e28a4053SRui Paulo 		bss->eap_req_id_text = os_strdup(pos);
2776e28a4053SRui Paulo 		if (bss->eap_req_id_text == NULL) {
27775b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text",
27785b9c547cSRui Paulo 				   line);
27795b9c547cSRui Paulo 			return 1;
2780e28a4053SRui Paulo 		}
27815b9c547cSRui Paulo 		bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text);
2782e28a4053SRui Paulo 		term = os_strstr(bss->eap_req_id_text, "\\0");
2783e28a4053SRui Paulo 		if (term) {
2784e28a4053SRui Paulo 			*term++ = '\0';
2785e28a4053SRui Paulo 			os_memmove(term, term + 1,
2786e28a4053SRui Paulo 				   bss->eap_req_id_text_len -
2787e28a4053SRui Paulo 				   (term - bss->eap_req_id_text) - 1);
2788e28a4053SRui Paulo 			bss->eap_req_id_text_len--;
2789e28a4053SRui Paulo 		}
27905b9c547cSRui Paulo 	} else if (os_strcmp(buf, "erp_send_reauth_start") == 0) {
27915b9c547cSRui Paulo 		bss->erp_send_reauth_start = atoi(pos);
27925b9c547cSRui Paulo 	} else if (os_strcmp(buf, "erp_domain") == 0) {
27935b9c547cSRui Paulo 		os_free(bss->erp_domain);
27945b9c547cSRui Paulo 		bss->erp_domain = os_strdup(pos);
2795c1d255d3SCy Schubert #ifdef CONFIG_WEP
2796e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
279785732ac8SCy Schubert 		int val = atoi(pos);
279885732ac8SCy Schubert 
279985732ac8SCy Schubert 		if (val < 0 || val > 13) {
280085732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
280185732ac8SCy Schubert 				   "Line %d: invalid WEP key len %d (= %d bits)",
280285732ac8SCy Schubert 				   line, val, val * 8);
28035b9c547cSRui Paulo 			return 1;
2804e28a4053SRui Paulo 		}
280585732ac8SCy Schubert 		bss->default_wep_key_len = val;
2806e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
280785732ac8SCy Schubert 		int val = atoi(pos);
280885732ac8SCy Schubert 
280985732ac8SCy Schubert 		if (val < 0 || val > 13) {
281085732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
281185732ac8SCy Schubert 				   "Line %d: invalid WEP key len %d (= %d bits)",
281285732ac8SCy Schubert 				   line, val, val * 8);
28135b9c547cSRui Paulo 			return 1;
2814e28a4053SRui Paulo 		}
281585732ac8SCy Schubert 		bss->individual_wep_key_len = val;
2816e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wep_rekey_period") == 0) {
2817e28a4053SRui Paulo 		bss->wep_rekeying_period = atoi(pos);
2818e28a4053SRui Paulo 		if (bss->wep_rekeying_period < 0) {
28195b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
2820e28a4053SRui Paulo 				   line, bss->wep_rekeying_period);
28215b9c547cSRui Paulo 			return 1;
2822e28a4053SRui Paulo 		}
2823c1d255d3SCy Schubert #endif /* CONFIG_WEP */
2824e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
2825e28a4053SRui Paulo 		bss->eap_reauth_period = atoi(pos);
2826e28a4053SRui Paulo 		if (bss->eap_reauth_period < 0) {
28275b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
2828e28a4053SRui Paulo 				   line, bss->eap_reauth_period);
28295b9c547cSRui Paulo 			return 1;
2830e28a4053SRui Paulo 		}
2831e28a4053SRui Paulo 	} else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
2832e28a4053SRui Paulo 		bss->eapol_key_index_workaround = atoi(pos);
2833e28a4053SRui Paulo #ifdef CONFIG_IAPP
2834e28a4053SRui Paulo 	} else if (os_strcmp(buf, "iapp_interface") == 0) {
2835c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
2836e28a4053SRui Paulo #endif /* CONFIG_IAPP */
2837e28a4053SRui Paulo 	} else if (os_strcmp(buf, "own_ip_addr") == 0) {
2838e28a4053SRui Paulo 		if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
28395b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
28405b9c547cSRui Paulo 				   "Line %d: invalid IP address '%s'",
28415b9c547cSRui Paulo 				   line, pos);
28425b9c547cSRui Paulo 			return 1;
2843e28a4053SRui Paulo 		}
2844e28a4053SRui Paulo 	} else if (os_strcmp(buf, "nas_identifier") == 0) {
28455b9c547cSRui Paulo 		os_free(bss->nas_identifier);
2846e28a4053SRui Paulo 		bss->nas_identifier = os_strdup(pos);
2847e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS
28485b9c547cSRui Paulo 	} else if (os_strcmp(buf, "radius_client_addr") == 0) {
28495b9c547cSRui Paulo 		if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) {
28505b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
28515b9c547cSRui Paulo 				   "Line %d: invalid IP address '%s'",
28525b9c547cSRui Paulo 				   line, pos);
28535b9c547cSRui Paulo 			return 1;
28545b9c547cSRui Paulo 		}
28555b9c547cSRui Paulo 		bss->radius->force_client_addr = 1;
2856c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "radius_client_dev") == 0) {
2857c1d255d3SCy Schubert 			os_free(bss->radius->force_client_dev);
2858c1d255d3SCy Schubert 			bss->radius->force_client_dev = os_strdup(pos);
2859e28a4053SRui Paulo 	} else if (os_strcmp(buf, "auth_server_addr") == 0) {
2860e28a4053SRui Paulo 		if (hostapd_config_read_radius_addr(
2861e28a4053SRui Paulo 			    &bss->radius->auth_servers,
2862e28a4053SRui Paulo 			    &bss->radius->num_auth_servers, pos, 1812,
2863e28a4053SRui Paulo 			    &bss->radius->auth_server)) {
28645b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
28655b9c547cSRui Paulo 				   "Line %d: invalid IP address '%s'",
28665b9c547cSRui Paulo 				   line, pos);
28675b9c547cSRui Paulo 			return 1;
28685b9c547cSRui Paulo 		}
28695b9c547cSRui Paulo 	} else if (bss->radius->auth_server &&
28705b9c547cSRui Paulo 		   os_strcmp(buf, "auth_server_addr_replace") == 0) {
28715b9c547cSRui Paulo 		if (hostapd_parse_ip_addr(pos,
28725b9c547cSRui Paulo 					  &bss->radius->auth_server->addr)) {
28735b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
28745b9c547cSRui Paulo 				   "Line %d: invalid IP address '%s'",
28755b9c547cSRui Paulo 				   line, pos);
28765b9c547cSRui Paulo 			return 1;
2877e28a4053SRui Paulo 		}
2878e28a4053SRui Paulo 	} else if (bss->radius->auth_server &&
2879e28a4053SRui Paulo 		   os_strcmp(buf, "auth_server_port") == 0) {
2880e28a4053SRui Paulo 		bss->radius->auth_server->port = atoi(pos);
2881e28a4053SRui Paulo 	} else if (bss->radius->auth_server &&
2882e28a4053SRui Paulo 		   os_strcmp(buf, "auth_server_shared_secret") == 0) {
2883e28a4053SRui Paulo 		int len = os_strlen(pos);
2884e28a4053SRui Paulo 		if (len == 0) {
2885e28a4053SRui Paulo 			/* RFC 2865, Ch. 3 */
28865b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
28875b9c547cSRui Paulo 				   line);
28885b9c547cSRui Paulo 			return 1;
2889e28a4053SRui Paulo 		}
28905b9c547cSRui Paulo 		os_free(bss->radius->auth_server->shared_secret);
28915b9c547cSRui Paulo 		bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
2892e28a4053SRui Paulo 		bss->radius->auth_server->shared_secret_len = len;
2893*a90b9d01SCy Schubert 	} else if (bss->radius->auth_server &&
2894*a90b9d01SCy Schubert 		   os_strcmp(buf, "auth_server_type") == 0) {
2895*a90b9d01SCy Schubert 		if (os_strcmp(pos, "UDP") == 0) {
2896*a90b9d01SCy Schubert 			bss->radius->auth_server->tls = false;
2897*a90b9d01SCy Schubert #ifdef CONFIG_RADIUS_TLS
2898*a90b9d01SCy Schubert 		} else if (os_strcmp(pos, "TLS") == 0) {
2899*a90b9d01SCy Schubert 			bss->radius->auth_server->tls = true;
2900*a90b9d01SCy Schubert #endif /* CONFIG_RADIUS_TLS */
2901*a90b9d01SCy Schubert 		} else {
2902*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
2903*a90b9d01SCy Schubert 				   line, pos);
2904*a90b9d01SCy Schubert 			return 1;
2905*a90b9d01SCy Schubert 		}
2906*a90b9d01SCy Schubert #ifdef CONFIG_RADIUS_TLS
2907*a90b9d01SCy Schubert 	} else if (bss->radius->auth_server &&
2908*a90b9d01SCy Schubert 		   os_strcmp(buf, "auth_server_ca_cert") == 0) {
2909*a90b9d01SCy Schubert 		os_free(bss->radius->auth_server->ca_cert);
2910*a90b9d01SCy Schubert 		bss->radius->auth_server->ca_cert = os_strdup(pos);
2911*a90b9d01SCy Schubert 	} else if (bss->radius->auth_server &&
2912*a90b9d01SCy Schubert 		   os_strcmp(buf, "auth_server_client_cert") == 0) {
2913*a90b9d01SCy Schubert 		os_free(bss->radius->auth_server->client_cert);
2914*a90b9d01SCy Schubert 		bss->radius->auth_server->client_cert = os_strdup(pos);
2915*a90b9d01SCy Schubert 	} else if (bss->radius->auth_server &&
2916*a90b9d01SCy Schubert 		   os_strcmp(buf, "auth_server_private_key") == 0) {
2917*a90b9d01SCy Schubert 		os_free(bss->radius->auth_server->private_key);
2918*a90b9d01SCy Schubert 		bss->radius->auth_server->private_key = os_strdup(pos);
2919*a90b9d01SCy Schubert 	} else if (bss->radius->auth_server &&
2920*a90b9d01SCy Schubert 		   os_strcmp(buf, "auth_server_private_key_passwd") == 0) {
2921*a90b9d01SCy Schubert 		os_free(bss->radius->auth_server->private_key_passwd);
2922*a90b9d01SCy Schubert 		bss->radius->auth_server->private_key_passwd = os_strdup(pos);
2923*a90b9d01SCy Schubert #endif /* CONFIG_RADIUS_TLS */
2924e28a4053SRui Paulo 	} else if (os_strcmp(buf, "acct_server_addr") == 0) {
2925e28a4053SRui Paulo 		if (hostapd_config_read_radius_addr(
2926e28a4053SRui Paulo 			    &bss->radius->acct_servers,
2927e28a4053SRui Paulo 			    &bss->radius->num_acct_servers, pos, 1813,
2928e28a4053SRui Paulo 			    &bss->radius->acct_server)) {
29295b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
29305b9c547cSRui Paulo 				   "Line %d: invalid IP address '%s'",
29315b9c547cSRui Paulo 				   line, pos);
29325b9c547cSRui Paulo 			return 1;
29335b9c547cSRui Paulo 		}
29345b9c547cSRui Paulo 	} else if (bss->radius->acct_server &&
29355b9c547cSRui Paulo 		   os_strcmp(buf, "acct_server_addr_replace") == 0) {
29365b9c547cSRui Paulo 		if (hostapd_parse_ip_addr(pos,
29375b9c547cSRui Paulo 					  &bss->radius->acct_server->addr)) {
29385b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
29395b9c547cSRui Paulo 				   "Line %d: invalid IP address '%s'",
29405b9c547cSRui Paulo 				   line, pos);
29415b9c547cSRui Paulo 			return 1;
2942e28a4053SRui Paulo 		}
2943e28a4053SRui Paulo 	} else if (bss->radius->acct_server &&
2944e28a4053SRui Paulo 		   os_strcmp(buf, "acct_server_port") == 0) {
2945e28a4053SRui Paulo 		bss->radius->acct_server->port = atoi(pos);
2946e28a4053SRui Paulo 	} else if (bss->radius->acct_server &&
2947e28a4053SRui Paulo 		   os_strcmp(buf, "acct_server_shared_secret") == 0) {
2948e28a4053SRui Paulo 		int len = os_strlen(pos);
2949e28a4053SRui Paulo 		if (len == 0) {
2950e28a4053SRui Paulo 			/* RFC 2865, Ch. 3 */
29515b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
29525b9c547cSRui Paulo 				   line);
29535b9c547cSRui Paulo 			return 1;
2954e28a4053SRui Paulo 		}
29555b9c547cSRui Paulo 		os_free(bss->radius->acct_server->shared_secret);
29565b9c547cSRui Paulo 		bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
2957e28a4053SRui Paulo 		bss->radius->acct_server->shared_secret_len = len;
2958*a90b9d01SCy Schubert 	} else if (bss->radius->acct_server &&
2959*a90b9d01SCy Schubert 		   os_strcmp(buf, "acct_server_type") == 0) {
2960*a90b9d01SCy Schubert 		if (os_strcmp(pos, "UDP") == 0) {
2961*a90b9d01SCy Schubert 			bss->radius->acct_server->tls = false;
2962*a90b9d01SCy Schubert #ifdef CONFIG_RADIUS_TLS
2963*a90b9d01SCy Schubert 		} else if (os_strcmp(pos, "TLS") == 0) {
2964*a90b9d01SCy Schubert 			bss->radius->acct_server->tls = true;
2965*a90b9d01SCy Schubert #endif /* CONFIG_RADIUS_TLS */
2966*a90b9d01SCy Schubert 		} else {
2967*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
2968*a90b9d01SCy Schubert 				   line, pos);
2969*a90b9d01SCy Schubert 			return 1;
2970*a90b9d01SCy Schubert 		}
2971*a90b9d01SCy Schubert #ifdef CONFIG_RADIUS_TLS
2972*a90b9d01SCy Schubert 	} else if (bss->radius->acct_server &&
2973*a90b9d01SCy Schubert 		   os_strcmp(buf, "acct_server_ca_cert") == 0) {
2974*a90b9d01SCy Schubert 		os_free(bss->radius->acct_server->ca_cert);
2975*a90b9d01SCy Schubert 		bss->radius->acct_server->ca_cert = os_strdup(pos);
2976*a90b9d01SCy Schubert 	} else if (bss->radius->acct_server &&
2977*a90b9d01SCy Schubert 		   os_strcmp(buf, "acct_server_client_cert") == 0) {
2978*a90b9d01SCy Schubert 		os_free(bss->radius->acct_server->client_cert);
2979*a90b9d01SCy Schubert 		bss->radius->acct_server->client_cert = os_strdup(pos);
2980*a90b9d01SCy Schubert 	} else if (bss->radius->acct_server &&
2981*a90b9d01SCy Schubert 		   os_strcmp(buf, "acct_server_private_key") == 0) {
2982*a90b9d01SCy Schubert 		os_free(bss->radius->acct_server->private_key);
2983*a90b9d01SCy Schubert 		bss->radius->acct_server->private_key = os_strdup(pos);
2984*a90b9d01SCy Schubert 	} else if (bss->radius->acct_server &&
2985*a90b9d01SCy Schubert 		   os_strcmp(buf, "acct_server_private_key_passwd") == 0) {
2986*a90b9d01SCy Schubert 		os_free(bss->radius->acct_server->private_key_passwd);
2987*a90b9d01SCy Schubert 		bss->radius->acct_server->private_key_passwd = os_strdup(pos);
2988*a90b9d01SCy Schubert #endif /* CONFIG_RADIUS_TLS */
29895b9c547cSRui Paulo 	} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
2990e28a4053SRui Paulo 		bss->radius->retry_primary_interval = atoi(pos);
2991*a90b9d01SCy Schubert 	} else if (os_strcmp(buf,
2992*a90b9d01SCy Schubert 			     "radius_require_message_authenticator") == 0) {
2993*a90b9d01SCy Schubert 		bss->radius_require_message_authenticator = atoi(pos);
29945b9c547cSRui Paulo 	} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
2995e28a4053SRui Paulo 		bss->acct_interim_interval = atoi(pos);
2996f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "radius_request_cui") == 0) {
2997f05cddf9SRui Paulo 		bss->radius_request_cui = atoi(pos);
2998f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
2999f05cddf9SRui Paulo 		struct hostapd_radius_attr *attr, *a;
3000f05cddf9SRui Paulo 		attr = hostapd_parse_radius_attr(pos);
3001f05cddf9SRui Paulo 		if (attr == NULL) {
30025b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
30035b9c547cSRui Paulo 				   "Line %d: invalid radius_auth_req_attr",
30045b9c547cSRui Paulo 				   line);
30055b9c547cSRui Paulo 			return 1;
3006f05cddf9SRui Paulo 		} else if (bss->radius_auth_req_attr == NULL) {
3007f05cddf9SRui Paulo 			bss->radius_auth_req_attr = attr;
3008f05cddf9SRui Paulo 		} else {
3009f05cddf9SRui Paulo 			a = bss->radius_auth_req_attr;
3010f05cddf9SRui Paulo 			while (a->next)
3011f05cddf9SRui Paulo 				a = a->next;
3012f05cddf9SRui Paulo 			a->next = attr;
3013f05cddf9SRui Paulo 		}
3014f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
3015f05cddf9SRui Paulo 		struct hostapd_radius_attr *attr, *a;
3016f05cddf9SRui Paulo 		attr = hostapd_parse_radius_attr(pos);
3017f05cddf9SRui Paulo 		if (attr == NULL) {
30185b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
30195b9c547cSRui Paulo 				   "Line %d: invalid radius_acct_req_attr",
30205b9c547cSRui Paulo 				   line);
30215b9c547cSRui Paulo 			return 1;
3022f05cddf9SRui Paulo 		} else if (bss->radius_acct_req_attr == NULL) {
3023f05cddf9SRui Paulo 			bss->radius_acct_req_attr = attr;
3024f05cddf9SRui Paulo 		} else {
3025f05cddf9SRui Paulo 			a = bss->radius_acct_req_attr;
3026f05cddf9SRui Paulo 			while (a->next)
3027f05cddf9SRui Paulo 				a = a->next;
3028f05cddf9SRui Paulo 			a->next = attr;
3029f05cddf9SRui Paulo 		}
3030206b73d0SCy Schubert 	} else if (os_strcmp(buf, "radius_req_attr_sqlite") == 0) {
3031206b73d0SCy Schubert 		os_free(bss->radius_req_attr_sqlite);
3032206b73d0SCy Schubert 		bss->radius_req_attr_sqlite = os_strdup(pos);
3033f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "radius_das_port") == 0) {
3034f05cddf9SRui Paulo 		bss->radius_das_port = atoi(pos);
3035f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "radius_das_client") == 0) {
3036f05cddf9SRui Paulo 		if (hostapd_parse_das_client(bss, pos) < 0) {
30375b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid DAS client",
30385b9c547cSRui Paulo 				   line);
30395b9c547cSRui Paulo 			return 1;
3040f05cddf9SRui Paulo 		}
3041f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "radius_das_time_window") == 0) {
3042f05cddf9SRui Paulo 		bss->radius_das_time_window = atoi(pos);
30435b9c547cSRui Paulo 	} else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
3044f05cddf9SRui Paulo 		bss->radius_das_require_event_timestamp = atoi(pos);
3045780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "radius_das_require_message_authenticator") ==
3046780fb4a2SCy Schubert 		   0) {
3047780fb4a2SCy Schubert 		bss->radius_das_require_message_authenticator = atoi(pos);
3048e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */
3049e28a4053SRui Paulo 	} else if (os_strcmp(buf, "auth_algs") == 0) {
3050e28a4053SRui Paulo 		bss->auth_algs = atoi(pos);
3051e28a4053SRui Paulo 		if (bss->auth_algs == 0) {
30525b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed",
3053e28a4053SRui Paulo 				   line);
30545b9c547cSRui Paulo 			return 1;
3055e28a4053SRui Paulo 		}
3056e28a4053SRui Paulo 	} else if (os_strcmp(buf, "max_num_sta") == 0) {
3057e28a4053SRui Paulo 		bss->max_num_sta = atoi(pos);
3058e28a4053SRui Paulo 		if (bss->max_num_sta < 0 ||
3059e28a4053SRui Paulo 		    bss->max_num_sta > MAX_STA_COUNT) {
30605b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
30615b9c547cSRui Paulo 				   line, bss->max_num_sta, MAX_STA_COUNT);
30625b9c547cSRui Paulo 			return 1;
3063e28a4053SRui Paulo 		}
3064e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa") == 0) {
3065e28a4053SRui Paulo 		bss->wpa = atoi(pos);
3066c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "extended_key_id") == 0) {
3067c1d255d3SCy Schubert 		int val = atoi(pos);
3068c1d255d3SCy Schubert 
3069c1d255d3SCy Schubert 		if (val < 0 || val > 2) {
3070c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
3071c1d255d3SCy Schubert 				   "Line %d: Invalid extended_key_id=%d; allowed range 0..2",
3072c1d255d3SCy Schubert 				   line, val);
3073c1d255d3SCy Schubert 			return 1;
3074c1d255d3SCy Schubert 		}
3075c1d255d3SCy Schubert 		bss->extended_key_id = val;
3076e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
3077e28a4053SRui Paulo 		bss->wpa_group_rekey = atoi(pos);
307885732ac8SCy Schubert 		bss->wpa_group_rekey_set = 1;
3079e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
3080e28a4053SRui Paulo 		bss->wpa_strict_rekey = atoi(pos);
3081e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
3082e28a4053SRui Paulo 		bss->wpa_gmk_rekey = atoi(pos);
3083e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
3084e28a4053SRui Paulo 		bss->wpa_ptk_rekey = atoi(pos);
3085c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
3086c1d255d3SCy Schubert 		bss->wpa_deny_ptk0_rekey = atoi(pos);
3087c1d255d3SCy Schubert 		if (bss->wpa_deny_ptk0_rekey < 0 ||
3088c1d255d3SCy Schubert 		    bss->wpa_deny_ptk0_rekey > 2) {
3089c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
3090c1d255d3SCy Schubert 				   "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
3091c1d255d3SCy Schubert 				   line, bss->wpa_deny_ptk0_rekey);
3092c1d255d3SCy Schubert 			return 1;
3093c1d255d3SCy Schubert 		}
309485732ac8SCy Schubert 	} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
309585732ac8SCy Schubert 		char *endp;
309685732ac8SCy Schubert 		unsigned long val = strtoul(pos, &endp, 0);
309785732ac8SCy Schubert 
309885732ac8SCy Schubert 		if (*endp || val < 1 || val > (u32) -1) {
309985732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
310085732ac8SCy Schubert 				   "Line %d: Invalid wpa_group_update_count=%lu; allowed range 1..4294967295",
310185732ac8SCy Schubert 				   line, val);
310285732ac8SCy Schubert 			return 1;
310385732ac8SCy Schubert 		}
310485732ac8SCy Schubert 		bss->wpa_group_update_count = (u32) val;
310585732ac8SCy Schubert 	} else if (os_strcmp(buf, "wpa_pairwise_update_count") == 0) {
310685732ac8SCy Schubert 		char *endp;
310785732ac8SCy Schubert 		unsigned long val = strtoul(pos, &endp, 0);
310885732ac8SCy Schubert 
310985732ac8SCy Schubert 		if (*endp || val < 1 || val > (u32) -1) {
311085732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
311185732ac8SCy Schubert 				   "Line %d: Invalid wpa_pairwise_update_count=%lu; allowed range 1..4294967295",
311285732ac8SCy Schubert 				   line, val);
311385732ac8SCy Schubert 			return 1;
311485732ac8SCy Schubert 		}
311585732ac8SCy Schubert 		bss->wpa_pairwise_update_count = (u32) val;
311685732ac8SCy Schubert 	} else if (os_strcmp(buf, "wpa_disable_eapol_key_retries") == 0) {
311785732ac8SCy Schubert 		bss->wpa_disable_eapol_key_retries = atoi(pos);
3118e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
3119e28a4053SRui Paulo 		int len = os_strlen(pos);
3120e28a4053SRui Paulo 		if (len < 8 || len > 63) {
31215b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)",
31225b9c547cSRui Paulo 				   line, len);
31235b9c547cSRui Paulo 			return 1;
31245b9c547cSRui Paulo 		}
3125e28a4053SRui Paulo 		os_free(bss->ssid.wpa_passphrase);
3126e28a4053SRui Paulo 		bss->ssid.wpa_passphrase = os_strdup(pos);
31275b9c547cSRui Paulo 		if (bss->ssid.wpa_passphrase) {
31285b9c547cSRui Paulo 			hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
31295b9c547cSRui Paulo 			bss->ssid.wpa_passphrase_set = 1;
3130e28a4053SRui Paulo 		}
3131e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_psk") == 0) {
31325b9c547cSRui Paulo 		hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
31335b9c547cSRui Paulo 		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
3134e28a4053SRui Paulo 		if (bss->ssid.wpa_psk == NULL)
31355b9c547cSRui Paulo 			return 1;
31365b9c547cSRui Paulo 		if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) ||
3137e28a4053SRui Paulo 		    pos[PMK_LEN * 2] != '\0') {
31385b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
31395b9c547cSRui Paulo 				   line, pos);
31405b9c547cSRui Paulo 			hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
31415b9c547cSRui Paulo 			return 1;
31425b9c547cSRui Paulo 		}
3143e28a4053SRui Paulo 		bss->ssid.wpa_psk->group = 1;
3144f05cddf9SRui Paulo 		os_free(bss->ssid.wpa_passphrase);
3145f05cddf9SRui Paulo 		bss->ssid.wpa_passphrase = NULL;
31465b9c547cSRui Paulo 		bss->ssid.wpa_psk_set = 1;
3147e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_psk_file") == 0) {
3148e28a4053SRui Paulo 		os_free(bss->ssid.wpa_psk_file);
3149e28a4053SRui Paulo 		bss->ssid.wpa_psk_file = os_strdup(pos);
3150e28a4053SRui Paulo 		if (!bss->ssid.wpa_psk_file) {
31515b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: allocation failed",
31525b9c547cSRui Paulo 				   line);
31535b9c547cSRui Paulo 			return 1;
3154e28a4053SRui Paulo 		}
3155e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
31565b9c547cSRui Paulo 		bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
3157e28a4053SRui Paulo 		if (bss->wpa_key_mgmt == -1)
31585b9c547cSRui Paulo 			return 1;
3159f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
3160f05cddf9SRui Paulo 		bss->wpa_psk_radius = atoi(pos);
3161f05cddf9SRui Paulo 		if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
3162f05cddf9SRui Paulo 		    bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
3163*a90b9d01SCy Schubert 		    bss->wpa_psk_radius != PSK_RADIUS_REQUIRED &&
3164*a90b9d01SCy Schubert 		    bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS) {
31655b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
31665b9c547cSRui Paulo 				   "Line %d: unknown wpa_psk_radius %d",
3167f05cddf9SRui Paulo 				   line, bss->wpa_psk_radius);
31685b9c547cSRui Paulo 			return 1;
3169f05cddf9SRui Paulo 		}
3170e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
31715b9c547cSRui Paulo 		bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos);
31725b9c547cSRui Paulo 		if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0)
31735b9c547cSRui Paulo 			return 1;
31745b9c547cSRui Paulo 		if (bss->wpa_pairwise &
31755b9c547cSRui Paulo 		    (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
31765b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
317785732ac8SCy Schubert 				   line, pos);
31785b9c547cSRui Paulo 			return 1;
3179e28a4053SRui Paulo 		}
3180e28a4053SRui Paulo 	} else if (os_strcmp(buf, "rsn_pairwise") == 0) {
31815b9c547cSRui Paulo 		bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos);
31825b9c547cSRui Paulo 		if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0)
31835b9c547cSRui Paulo 			return 1;
31845b9c547cSRui Paulo 		if (bss->rsn_pairwise &
31855b9c547cSRui Paulo 		    (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
31865b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
318785732ac8SCy Schubert 				   line, pos);
318885732ac8SCy Schubert 			return 1;
318985732ac8SCy Schubert 		}
319085732ac8SCy Schubert 	} else if (os_strcmp(buf, "group_cipher") == 0) {
319185732ac8SCy Schubert 		bss->group_cipher = hostapd_config_parse_cipher(line, pos);
319285732ac8SCy Schubert 		if (bss->group_cipher == -1 || bss->group_cipher == 0)
319385732ac8SCy Schubert 			return 1;
319485732ac8SCy Schubert 		if (bss->group_cipher != WPA_CIPHER_TKIP &&
319585732ac8SCy Schubert 		    bss->group_cipher != WPA_CIPHER_CCMP &&
319685732ac8SCy Schubert 		    bss->group_cipher != WPA_CIPHER_GCMP &&
319785732ac8SCy Schubert 		    bss->group_cipher != WPA_CIPHER_GCMP_256 &&
319885732ac8SCy Schubert 		    bss->group_cipher != WPA_CIPHER_CCMP_256) {
319985732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
320085732ac8SCy Schubert 				   "Line %d: unsupported group cipher suite '%s'",
320185732ac8SCy Schubert 				   line, pos);
32025b9c547cSRui Paulo 			return 1;
3203e28a4053SRui Paulo 		}
3204e28a4053SRui Paulo #ifdef CONFIG_RSN_PREAUTH
3205e28a4053SRui Paulo 	} else if (os_strcmp(buf, "rsn_preauth") == 0) {
3206e28a4053SRui Paulo 		bss->rsn_preauth = atoi(pos);
3207e28a4053SRui Paulo 	} else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
32085b9c547cSRui Paulo 		os_free(bss->rsn_preauth_interfaces);
3209e28a4053SRui Paulo 		bss->rsn_preauth_interfaces = os_strdup(pos);
3210e28a4053SRui Paulo #endif /* CONFIG_RSN_PREAUTH */
3211e28a4053SRui Paulo 	} else if (os_strcmp(buf, "peerkey") == 0) {
321285732ac8SCy Schubert 		wpa_printf(MSG_INFO,
321385732ac8SCy Schubert 			   "Line %d: Obsolete peerkey parameter ignored", line);
321485732ac8SCy Schubert #ifdef CONFIG_IEEE80211R_AP
3215e28a4053SRui Paulo 	} else if (os_strcmp(buf, "mobility_domain") == 0) {
3216e28a4053SRui Paulo 		if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
3217e28a4053SRui Paulo 		    hexstr2bin(pos, bss->mobility_domain,
3218e28a4053SRui Paulo 			       MOBILITY_DOMAIN_ID_LEN) != 0) {
32195b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
32205b9c547cSRui Paulo 				   "Line %d: Invalid mobility_domain '%s'",
32215b9c547cSRui Paulo 				   line, pos);
32225b9c547cSRui Paulo 			return 1;
3223e28a4053SRui Paulo 		}
3224e28a4053SRui Paulo 	} else if (os_strcmp(buf, "r1_key_holder") == 0) {
3225e28a4053SRui Paulo 		if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
32265b9c547cSRui Paulo 		    hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) {
32275b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
32285b9c547cSRui Paulo 				   "Line %d: Invalid r1_key_holder '%s'",
32295b9c547cSRui Paulo 				   line, pos);
32305b9c547cSRui Paulo 			return 1;
3231e28a4053SRui Paulo 		}
3232e28a4053SRui Paulo 	} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
323385732ac8SCy Schubert 		/* DEPRECATED: Use ft_r0_key_lifetime instead. */
323485732ac8SCy Schubert 		bss->r0_key_lifetime = atoi(pos) * 60;
323585732ac8SCy Schubert 	} else if (os_strcmp(buf, "ft_r0_key_lifetime") == 0) {
3236e28a4053SRui Paulo 		bss->r0_key_lifetime = atoi(pos);
323785732ac8SCy Schubert 	} else if (os_strcmp(buf, "r1_max_key_lifetime") == 0) {
323885732ac8SCy Schubert 		bss->r1_max_key_lifetime = atoi(pos);
3239e28a4053SRui Paulo 	} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
3240e28a4053SRui Paulo 		bss->reassociation_deadline = atoi(pos);
324185732ac8SCy Schubert 	} else if (os_strcmp(buf, "rkh_pos_timeout") == 0) {
324285732ac8SCy Schubert 		bss->rkh_pos_timeout = atoi(pos);
324385732ac8SCy Schubert 	} else if (os_strcmp(buf, "rkh_neg_timeout") == 0) {
324485732ac8SCy Schubert 		bss->rkh_neg_timeout = atoi(pos);
324585732ac8SCy Schubert 	} else if (os_strcmp(buf, "rkh_pull_timeout") == 0) {
324685732ac8SCy Schubert 		bss->rkh_pull_timeout = atoi(pos);
324785732ac8SCy Schubert 	} else if (os_strcmp(buf, "rkh_pull_retries") == 0) {
324885732ac8SCy Schubert 		bss->rkh_pull_retries = atoi(pos);
3249e28a4053SRui Paulo 	} else if (os_strcmp(buf, "r0kh") == 0) {
3250e28a4053SRui Paulo 		if (add_r0kh(bss, pos) < 0) {
32515b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'",
32525b9c547cSRui Paulo 				   line, pos);
32535b9c547cSRui Paulo 			return 1;
3254e28a4053SRui Paulo 		}
3255e28a4053SRui Paulo 	} else if (os_strcmp(buf, "r1kh") == 0) {
3256e28a4053SRui Paulo 		if (add_r1kh(bss, pos) < 0) {
32575b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'",
32585b9c547cSRui Paulo 				   line, pos);
32595b9c547cSRui Paulo 			return 1;
3260e28a4053SRui Paulo 		}
3261*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "rxkh_file") == 0) {
3262*a90b9d01SCy Schubert 		os_free(bss->rxkh_file);
3263*a90b9d01SCy Schubert 		bss->rxkh_file = os_strdup(pos);
3264*a90b9d01SCy Schubert 		if (!bss->rxkh_file) {
3265*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: allocation failed",
3266*a90b9d01SCy Schubert 				   line);
3267*a90b9d01SCy Schubert 			return 1;
3268*a90b9d01SCy Schubert 		}
3269*a90b9d01SCy Schubert 		if (hostapd_config_read_rxkh_file(bss, pos)) {
3270*a90b9d01SCy Schubert 			wpa_printf(MSG_DEBUG,
3271*a90b9d01SCy Schubert 				   "Line %d: failed to read rxkh_file '%s'",
3272*a90b9d01SCy Schubert 				   line, pos);
3273*a90b9d01SCy Schubert 			/* Allow the file to be created later and read into
3274*a90b9d01SCy Schubert 			 * already operating AP context. */
3275*a90b9d01SCy Schubert 		}
3276e28a4053SRui Paulo 	} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
3277e28a4053SRui Paulo 		bss->pmk_r1_push = atoi(pos);
3278f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "ft_over_ds") == 0) {
3279f05cddf9SRui Paulo 		bss->ft_over_ds = atoi(pos);
328085732ac8SCy Schubert 	} else if (os_strcmp(buf, "ft_psk_generate_local") == 0) {
328185732ac8SCy Schubert 		bss->ft_psk_generate_local = atoi(pos);
328285732ac8SCy Schubert #endif /* CONFIG_IEEE80211R_AP */
3283e28a4053SRui Paulo #ifndef CONFIG_NO_CTRL_IFACE
3284e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ctrl_interface") == 0) {
3285e28a4053SRui Paulo 		os_free(bss->ctrl_interface);
3286e28a4053SRui Paulo 		bss->ctrl_interface = os_strdup(pos);
3287e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
3288e28a4053SRui Paulo #ifndef CONFIG_NATIVE_WINDOWS
3289e28a4053SRui Paulo 		struct group *grp;
3290e28a4053SRui Paulo 		char *endp;
3291e28a4053SRui Paulo 		const char *group = pos;
3292e28a4053SRui Paulo 
3293e28a4053SRui Paulo 		grp = getgrnam(group);
3294e28a4053SRui Paulo 		if (grp) {
3295e28a4053SRui Paulo 			bss->ctrl_interface_gid = grp->gr_gid;
3296e28a4053SRui Paulo 			bss->ctrl_interface_gid_set = 1;
32975b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')",
3298e28a4053SRui Paulo 				   bss->ctrl_interface_gid, group);
32995b9c547cSRui Paulo 			return 0;
3300e28a4053SRui Paulo 		}
3301e28a4053SRui Paulo 
3302e28a4053SRui Paulo 		/* Group name not found - try to parse this as gid */
3303e28a4053SRui Paulo 		bss->ctrl_interface_gid = strtol(group, &endp, 10);
3304e28a4053SRui Paulo 		if (*group == '\0' || *endp != '\0') {
33055b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'",
33065b9c547cSRui Paulo 				   line, group);
33075b9c547cSRui Paulo 			return 1;
3308e28a4053SRui Paulo 		}
3309e28a4053SRui Paulo 		bss->ctrl_interface_gid_set = 1;
3310e28a4053SRui Paulo 		wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
3311e28a4053SRui Paulo 			   bss->ctrl_interface_gid);
3312e28a4053SRui Paulo #endif /* CONFIG_NATIVE_WINDOWS */
3313e28a4053SRui Paulo #endif /* CONFIG_NO_CTRL_IFACE */
3314e28a4053SRui Paulo #ifdef RADIUS_SERVER
3315e28a4053SRui Paulo 	} else if (os_strcmp(buf, "radius_server_clients") == 0) {
3316e28a4053SRui Paulo 		os_free(bss->radius_server_clients);
3317e28a4053SRui Paulo 		bss->radius_server_clients = os_strdup(pos);
3318e28a4053SRui Paulo 	} else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
3319e28a4053SRui Paulo 		bss->radius_server_auth_port = atoi(pos);
33205b9c547cSRui Paulo 	} else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
33215b9c547cSRui Paulo 		bss->radius_server_acct_port = atoi(pos);
3322e28a4053SRui Paulo 	} else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
3323e28a4053SRui Paulo 		bss->radius_server_ipv6 = atoi(pos);
3324e28a4053SRui Paulo #endif /* RADIUS_SERVER */
3325e28a4053SRui Paulo 	} else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
3326e28a4053SRui Paulo 		bss->use_pae_group_addr = atoi(pos);
3327e28a4053SRui Paulo 	} else if (os_strcmp(buf, "hw_mode") == 0) {
3328e28a4053SRui Paulo 		if (os_strcmp(pos, "a") == 0)
3329e28a4053SRui Paulo 			conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
3330e28a4053SRui Paulo 		else if (os_strcmp(pos, "b") == 0)
3331e28a4053SRui Paulo 			conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
3332e28a4053SRui Paulo 		else if (os_strcmp(pos, "g") == 0)
3333e28a4053SRui Paulo 			conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
3334f05cddf9SRui Paulo 		else if (os_strcmp(pos, "ad") == 0)
3335f05cddf9SRui Paulo 			conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
3336325151a3SRui Paulo 		else if (os_strcmp(pos, "any") == 0)
3337325151a3SRui Paulo 			conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
3338e28a4053SRui Paulo 		else {
33395b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
33405b9c547cSRui Paulo 				   line, pos);
33415b9c547cSRui Paulo 			return 1;
3342e28a4053SRui Paulo 		}
3343*a90b9d01SCy Schubert 		conf->hw_mode_set = true;
3344f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
3345325151a3SRui Paulo 		if (os_strcmp(pos, "ad") == 0)
3346325151a3SRui Paulo 			bss->wps_rf_bands = WPS_RF_60GHZ;
3347325151a3SRui Paulo 		else if (os_strcmp(pos, "a") == 0)
3348f05cddf9SRui Paulo 			bss->wps_rf_bands = WPS_RF_50GHZ;
3349f05cddf9SRui Paulo 		else if (os_strcmp(pos, "g") == 0 ||
3350f05cddf9SRui Paulo 			 os_strcmp(pos, "b") == 0)
3351f05cddf9SRui Paulo 			bss->wps_rf_bands = WPS_RF_24GHZ;
3352f05cddf9SRui Paulo 		else if (os_strcmp(pos, "ag") == 0 ||
3353f05cddf9SRui Paulo 			 os_strcmp(pos, "ga") == 0)
33545b9c547cSRui Paulo 			bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
3355f05cddf9SRui Paulo 		else {
33565b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
33575b9c547cSRui Paulo 				   "Line %d: unknown wps_rf_band '%s'",
33585b9c547cSRui Paulo 				   line, pos);
33595b9c547cSRui Paulo 			return 1;
3360f05cddf9SRui Paulo 		}
336185732ac8SCy Schubert 	} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
336285732ac8SCy Schubert 		conf->acs_exclude_dfs = atoi(pos);
3363c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "op_class") == 0) {
3364c1d255d3SCy Schubert 		conf->op_class = atoi(pos);
3365e28a4053SRui Paulo 	} else if (os_strcmp(buf, "channel") == 0) {
33665b9c547cSRui Paulo 		if (os_strcmp(pos, "acs_survey") == 0) {
33675b9c547cSRui Paulo #ifndef CONFIG_ACS
33685b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled",
33695b9c547cSRui Paulo 				   line);
33705b9c547cSRui Paulo 			return 1;
33715b9c547cSRui Paulo #else /* CONFIG_ACS */
3372325151a3SRui Paulo 			conf->acs = 1;
33735b9c547cSRui Paulo 			conf->channel = 0;
33745b9c547cSRui Paulo #endif /* CONFIG_ACS */
3375325151a3SRui Paulo 		} else {
3376e28a4053SRui Paulo 			conf->channel = atoi(pos);
3377325151a3SRui Paulo 			conf->acs = conf->channel == 0;
3378325151a3SRui Paulo 		}
3379c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "edmg_channel") == 0) {
3380c1d255d3SCy Schubert 		conf->edmg_channel = atoi(pos);
3381c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "enable_edmg") == 0) {
3382c1d255d3SCy Schubert 		conf->enable_edmg = atoi(pos);
33835b9c547cSRui Paulo 	} else if (os_strcmp(buf, "chanlist") == 0) {
3384325151a3SRui Paulo 		if (hostapd_parse_chanlist(conf, pos)) {
33855b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
33865b9c547cSRui Paulo 				   line);
33875b9c547cSRui Paulo 			return 1;
33885b9c547cSRui Paulo 		}
3389c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "freqlist") == 0) {
3390c1d255d3SCy Schubert 		if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
3391c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
3392c1d255d3SCy Schubert 				   line);
3393c1d255d3SCy Schubert 			return 1;
3394c1d255d3SCy Schubert 		}
3395c1d255d3SCy Schubert 		conf->acs_freq_list_present = 1;
3396c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
3397c1d255d3SCy Schubert 		conf->acs_exclude_6ghz_non_psc = atoi(pos);
3398*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "enable_background_radar") == 0) {
3399*a90b9d01SCy Schubert 		conf->enable_background_radar = atoi(pos);
340032a95656SCy Schubert 	} else if (os_strcmp(buf, "min_tx_power") == 0) {
340132a95656SCy Schubert 		int val = atoi(pos);
340232a95656SCy Schubert 
340332a95656SCy Schubert 		if (val < 0 || val > 255) {
340432a95656SCy Schubert 			wpa_printf(MSG_ERROR,
340532a95656SCy Schubert 				   "Line %d: invalid min_tx_power %d (expected 0..255)",
340632a95656SCy Schubert 				   line, val);
340732a95656SCy Schubert 			return 1;
340832a95656SCy Schubert 		}
340932a95656SCy Schubert 		conf->min_tx_power = val;
3410e28a4053SRui Paulo 	} else if (os_strcmp(buf, "beacon_int") == 0) {
3411e28a4053SRui Paulo 		int val = atoi(pos);
3412e28a4053SRui Paulo 		/* MIB defines range as 1..65535, but very small values
3413e28a4053SRui Paulo 		 * cause problems with the current implementation.
3414e28a4053SRui Paulo 		 * Since it is unlikely that this small numbers are
3415e28a4053SRui Paulo 		 * useful in real life scenarios, do not allow beacon
34164bc52338SCy Schubert 		 * period to be set below 10 TU. */
34174bc52338SCy Schubert 		if (val < 10 || val > 65535) {
34184bc52338SCy Schubert 			wpa_printf(MSG_ERROR,
34194bc52338SCy Schubert 				   "Line %d: invalid beacon_int %d (expected 10..65535)",
34205b9c547cSRui Paulo 				   line, val);
34215b9c547cSRui Paulo 			return 1;
34225b9c547cSRui Paulo 		}
3423e28a4053SRui Paulo 		conf->beacon_int = val;
34245b9c547cSRui Paulo #ifdef CONFIG_ACS
34255b9c547cSRui Paulo 	} else if (os_strcmp(buf, "acs_num_scans") == 0) {
34265b9c547cSRui Paulo 		int val = atoi(pos);
34275b9c547cSRui Paulo 		if (val <= 0 || val > 100) {
34285b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)",
34295b9c547cSRui Paulo 				   line, val);
34305b9c547cSRui Paulo 			return 1;
34315b9c547cSRui Paulo 		}
34325b9c547cSRui Paulo 		conf->acs_num_scans = val;
34335b9c547cSRui Paulo 	} else if (os_strcmp(buf, "acs_chan_bias") == 0) {
34345b9c547cSRui Paulo 		if (hostapd_config_parse_acs_chan_bias(conf, pos)) {
34355b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias",
34365b9c547cSRui Paulo 				   line);
34375b9c547cSRui Paulo 			return -1;
34385b9c547cSRui Paulo 		}
34395b9c547cSRui Paulo #endif /* CONFIG_ACS */
3440e28a4053SRui Paulo 	} else if (os_strcmp(buf, "dtim_period") == 0) {
344185732ac8SCy Schubert 		int val = atoi(pos);
344285732ac8SCy Schubert 
344385732ac8SCy Schubert 		if (val < 1 || val > 255) {
34445b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d",
344585732ac8SCy Schubert 				   line, val);
34465b9c547cSRui Paulo 			return 1;
34475b9c547cSRui Paulo 		}
344885732ac8SCy Schubert 		bss->dtim_period = val;
34495b9c547cSRui Paulo 	} else if (os_strcmp(buf, "bss_load_update_period") == 0) {
345085732ac8SCy Schubert 		int val = atoi(pos);
345185732ac8SCy Schubert 
345285732ac8SCy Schubert 		if (val < 0 || val > 100) {
34535b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
34545b9c547cSRui Paulo 				   "Line %d: invalid bss_load_update_period %d",
345585732ac8SCy Schubert 				   line, val);
34565b9c547cSRui Paulo 			return 1;
3457e28a4053SRui Paulo 		}
345885732ac8SCy Schubert 		bss->bss_load_update_period = val;
345985732ac8SCy Schubert 	} else if (os_strcmp(buf, "chan_util_avg_period") == 0) {
346085732ac8SCy Schubert 		int val = atoi(pos);
346185732ac8SCy Schubert 
346285732ac8SCy Schubert 		if (val < 0) {
346385732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
346485732ac8SCy Schubert 				   "Line %d: invalid chan_util_avg_period",
346585732ac8SCy Schubert 				   line);
346685732ac8SCy Schubert 			return 1;
346785732ac8SCy Schubert 		}
346885732ac8SCy Schubert 		bss->chan_util_avg_period = val;
3469e28a4053SRui Paulo 	} else if (os_strcmp(buf, "rts_threshold") == 0) {
3470e28a4053SRui Paulo 		conf->rts_threshold = atoi(pos);
3471780fb4a2SCy Schubert 		if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) {
34725b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
34735b9c547cSRui Paulo 				   "Line %d: invalid rts_threshold %d",
3474e28a4053SRui Paulo 				   line, conf->rts_threshold);
34755b9c547cSRui Paulo 			return 1;
3476e28a4053SRui Paulo 		}
3477e28a4053SRui Paulo 	} else if (os_strcmp(buf, "fragm_threshold") == 0) {
3478e28a4053SRui Paulo 		conf->fragm_threshold = atoi(pos);
3479780fb4a2SCy Schubert 		if (conf->fragm_threshold == -1) {
3480780fb4a2SCy Schubert 			/* allow a value of -1 */
3481780fb4a2SCy Schubert 		} else if (conf->fragm_threshold < 256 ||
3482e28a4053SRui Paulo 			   conf->fragm_threshold > 2346) {
34835b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
34845b9c547cSRui Paulo 				   "Line %d: invalid fragm_threshold %d",
3485e28a4053SRui Paulo 				   line, conf->fragm_threshold);
34865b9c547cSRui Paulo 			return 1;
3487e28a4053SRui Paulo 		}
3488e28a4053SRui Paulo 	} else if (os_strcmp(buf, "send_probe_response") == 0) {
3489e28a4053SRui Paulo 		int val = atoi(pos);
3490e28a4053SRui Paulo 		if (val != 0 && val != 1) {
34915b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)",
34925b9c547cSRui Paulo 				   line, val);
34935b9c547cSRui Paulo 			return 1;
34945b9c547cSRui Paulo 		}
34954bc52338SCy Schubert 		bss->send_probe_response = val;
3496e28a4053SRui Paulo 	} else if (os_strcmp(buf, "supported_rates") == 0) {
34975b9c547cSRui Paulo 		if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
34985b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
34995b9c547cSRui Paulo 				   line);
35005b9c547cSRui Paulo 			return 1;
3501e28a4053SRui Paulo 		}
3502e28a4053SRui Paulo 	} else if (os_strcmp(buf, "basic_rates") == 0) {
35035b9c547cSRui Paulo 		if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
35045b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
35055b9c547cSRui Paulo 				   line);
35065b9c547cSRui Paulo 			return 1;
3507e28a4053SRui Paulo 		}
350885732ac8SCy Schubert 	} else if (os_strcmp(buf, "beacon_rate") == 0) {
350985732ac8SCy Schubert 		int val;
351085732ac8SCy Schubert 
351185732ac8SCy Schubert 		if (os_strncmp(pos, "ht:", 3) == 0) {
351285732ac8SCy Schubert 			val = atoi(pos + 3);
351385732ac8SCy Schubert 			if (val < 0 || val > 31) {
351485732ac8SCy Schubert 				wpa_printf(MSG_ERROR,
351585732ac8SCy Schubert 					   "Line %d: invalid beacon_rate HT-MCS %d",
351685732ac8SCy Schubert 					   line, val);
351785732ac8SCy Schubert 				return 1;
351885732ac8SCy Schubert 			}
351985732ac8SCy Schubert 			conf->rate_type = BEACON_RATE_HT;
352085732ac8SCy Schubert 			conf->beacon_rate = val;
352185732ac8SCy Schubert 		} else if (os_strncmp(pos, "vht:", 4) == 0) {
352285732ac8SCy Schubert 			val = atoi(pos + 4);
352385732ac8SCy Schubert 			if (val < 0 || val > 9) {
352485732ac8SCy Schubert 				wpa_printf(MSG_ERROR,
352585732ac8SCy Schubert 					   "Line %d: invalid beacon_rate VHT-MCS %d",
352685732ac8SCy Schubert 					   line, val);
352785732ac8SCy Schubert 				return 1;
352885732ac8SCy Schubert 			}
352985732ac8SCy Schubert 			conf->rate_type = BEACON_RATE_VHT;
353085732ac8SCy Schubert 			conf->beacon_rate = val;
3531c1d255d3SCy Schubert 		} else if (os_strncmp(pos, "he:", 3) == 0) {
3532c1d255d3SCy Schubert 			val = atoi(pos + 3);
3533c1d255d3SCy Schubert 			if (val < 0 || val > 11) {
3534c1d255d3SCy Schubert 				wpa_printf(MSG_ERROR,
3535c1d255d3SCy Schubert 					   "Line %d: invalid beacon_rate HE-MCS %d",
3536c1d255d3SCy Schubert 					   line, val);
3537c1d255d3SCy Schubert 				return 1;
3538c1d255d3SCy Schubert 			}
3539c1d255d3SCy Schubert 			conf->rate_type = BEACON_RATE_HE;
3540c1d255d3SCy Schubert 			conf->beacon_rate = val;
354185732ac8SCy Schubert 		} else {
354285732ac8SCy Schubert 			val = atoi(pos);
354385732ac8SCy Schubert 			if (val < 10 || val > 10000) {
354485732ac8SCy Schubert 				wpa_printf(MSG_ERROR,
354585732ac8SCy Schubert 					   "Line %d: invalid legacy beacon_rate %d",
354685732ac8SCy Schubert 					   line, val);
354785732ac8SCy Schubert 				return 1;
354885732ac8SCy Schubert 			}
354985732ac8SCy Schubert 			conf->rate_type = BEACON_RATE_LEGACY;
355085732ac8SCy Schubert 			conf->beacon_rate = val;
355185732ac8SCy Schubert 		}
3552e28a4053SRui Paulo 	} else if (os_strcmp(buf, "preamble") == 0) {
3553e28a4053SRui Paulo 		if (atoi(pos))
3554e28a4053SRui Paulo 			conf->preamble = SHORT_PREAMBLE;
3555e28a4053SRui Paulo 		else
3556e28a4053SRui Paulo 			conf->preamble = LONG_PREAMBLE;
3557e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
3558e28a4053SRui Paulo 		bss->ignore_broadcast_ssid = atoi(pos);
3559780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
3560780fb4a2SCy Schubert 		bss->no_probe_resp_if_max_sta = atoi(pos);
3561c1d255d3SCy Schubert #ifdef CONFIG_WEP
3562e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wep_default_key") == 0) {
3563e28a4053SRui Paulo 		bss->ssid.wep.idx = atoi(pos);
3564e28a4053SRui Paulo 		if (bss->ssid.wep.idx > 3) {
35655b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
35665b9c547cSRui Paulo 				   "Invalid wep_default_key index %d",
3567e28a4053SRui Paulo 				   bss->ssid.wep.idx);
35685b9c547cSRui Paulo 			return 1;
3569e28a4053SRui Paulo 		}
3570e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wep_key0") == 0 ||
3571e28a4053SRui Paulo 		   os_strcmp(buf, "wep_key1") == 0 ||
3572e28a4053SRui Paulo 		   os_strcmp(buf, "wep_key2") == 0 ||
3573e28a4053SRui Paulo 		   os_strcmp(buf, "wep_key3") == 0) {
3574e28a4053SRui Paulo 		if (hostapd_config_read_wep(&bss->ssid.wep,
3575e28a4053SRui Paulo 					    buf[7] - '0', pos)) {
35765b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'",
35775b9c547cSRui Paulo 				   line, buf);
35785b9c547cSRui Paulo 			return 1;
3579e28a4053SRui Paulo 		}
3580c1d255d3SCy Schubert #endif /* CONFIG_WEP */
3581e28a4053SRui Paulo #ifndef CONFIG_NO_VLAN
3582e28a4053SRui Paulo 	} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
3583e28a4053SRui Paulo 		bss->ssid.dynamic_vlan = atoi(pos);
3584780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "per_sta_vif") == 0) {
3585780fb4a2SCy Schubert 		bss->ssid.per_sta_vif = atoi(pos);
3586e28a4053SRui Paulo 	} else if (os_strcmp(buf, "vlan_file") == 0) {
3587e28a4053SRui Paulo 		if (hostapd_config_read_vlan_file(bss, pos)) {
35885b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
35895b9c547cSRui Paulo 				   line, pos);
35905b9c547cSRui Paulo 			return 1;
3591e28a4053SRui Paulo 		}
3592f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "vlan_naming") == 0) {
3593f05cddf9SRui Paulo 		bss->ssid.vlan_naming = atoi(pos);
3594f05cddf9SRui Paulo 		if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
3595f05cddf9SRui Paulo 		    bss->ssid.vlan_naming < 0) {
35965b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
35975b9c547cSRui Paulo 				   "Line %d: invalid naming scheme %d",
35985b9c547cSRui Paulo 				   line, bss->ssid.vlan_naming);
35995b9c547cSRui Paulo 			return 1;
3600f05cddf9SRui Paulo 		}
3601e28a4053SRui Paulo #ifdef CONFIG_FULL_DYNAMIC_VLAN
3602e28a4053SRui Paulo 	} else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
36035b9c547cSRui Paulo 		os_free(bss->ssid.vlan_tagged_interface);
3604e28a4053SRui Paulo 		bss->ssid.vlan_tagged_interface = os_strdup(pos);
3605e28a4053SRui Paulo #endif /* CONFIG_FULL_DYNAMIC_VLAN */
3606e28a4053SRui Paulo #endif /* CONFIG_NO_VLAN */
3607e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ap_table_max_size") == 0) {
3608e28a4053SRui Paulo 		conf->ap_table_max_size = atoi(pos);
3609e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
3610e28a4053SRui Paulo 		conf->ap_table_expiration_time = atoi(pos);
3611e28a4053SRui Paulo 	} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
3612c1d255d3SCy Schubert 		if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) {
36135b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
36145b9c547cSRui Paulo 				   line);
36155b9c547cSRui Paulo 			return 1;
3616e28a4053SRui Paulo 		}
3617e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wme_enabled") == 0 ||
3618e28a4053SRui Paulo 		   os_strcmp(buf, "wmm_enabled") == 0) {
3619e28a4053SRui Paulo 		bss->wmm_enabled = atoi(pos);
3620e28a4053SRui Paulo 	} else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
3621e28a4053SRui Paulo 		bss->wmm_uapsd = atoi(pos);
3622e28a4053SRui Paulo 	} else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
3623e28a4053SRui Paulo 		   os_strncmp(buf, "wmm_ac_", 7) == 0) {
36245b9c547cSRui Paulo 		if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) {
36255b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item",
36265b9c547cSRui Paulo 				   line);
36275b9c547cSRui Paulo 			return 1;
3628e28a4053SRui Paulo 		}
3629e28a4053SRui Paulo 	} else if (os_strcmp(buf, "bss") == 0) {
3630e28a4053SRui Paulo 		if (hostapd_config_bss(conf, pos)) {
36315b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid bss item",
36325b9c547cSRui Paulo 				   line);
36335b9c547cSRui Paulo 			return 1;
3634e28a4053SRui Paulo 		}
3635e28a4053SRui Paulo 	} else if (os_strcmp(buf, "bssid") == 0) {
3636e28a4053SRui Paulo 		if (hwaddr_aton(pos, bss->bssid)) {
36375b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid bssid item",
36385b9c547cSRui Paulo 				   line);
36395b9c547cSRui Paulo 			return 1;
3640e28a4053SRui Paulo 		}
3641780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
3642780fb4a2SCy Schubert 		conf->use_driver_iface_addr = atoi(pos);
3643e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ieee80211w") == 0) {
3644e28a4053SRui Paulo 		bss->ieee80211w = atoi(pos);
36455b9c547cSRui Paulo 	} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
36465b9c547cSRui Paulo 		if (os_strcmp(pos, "AES-128-CMAC") == 0) {
36475b9c547cSRui Paulo 			bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
36485b9c547cSRui Paulo 		} else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
36495b9c547cSRui Paulo 			bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
36505b9c547cSRui Paulo 		} else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
36515b9c547cSRui Paulo 			bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
36525b9c547cSRui Paulo 		} else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
36535b9c547cSRui Paulo 			bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
36545b9c547cSRui Paulo 		} else {
36555b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
36565b9c547cSRui Paulo 				   line, pos);
36575b9c547cSRui Paulo 			return 1;
36585b9c547cSRui Paulo 		}
3659c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "beacon_prot") == 0) {
3660c1d255d3SCy Schubert 		bss->beacon_prot = atoi(pos);
3661e28a4053SRui Paulo 	} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
3662e28a4053SRui Paulo 		bss->assoc_sa_query_max_timeout = atoi(pos);
3663e28a4053SRui Paulo 		if (bss->assoc_sa_query_max_timeout == 0) {
36645b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout",
36655b9c547cSRui Paulo 				   line);
36665b9c547cSRui Paulo 			return 1;
3667e28a4053SRui Paulo 		}
36685b9c547cSRui Paulo 	} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) {
3669e28a4053SRui Paulo 		bss->assoc_sa_query_retry_timeout = atoi(pos);
3670e28a4053SRui Paulo 		if (bss->assoc_sa_query_retry_timeout == 0) {
36715b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout",
3672e28a4053SRui Paulo 				   line);
36735b9c547cSRui Paulo 			return 1;
3674e28a4053SRui Paulo 		}
36754bc52338SCy Schubert #ifdef CONFIG_OCV
36764bc52338SCy Schubert 	} else if (os_strcmp(buf, "ocv") == 0) {
36774bc52338SCy Schubert 		bss->ocv = atoi(pos);
36784bc52338SCy Schubert 		if (bss->ocv && !bss->ieee80211w)
36794bc52338SCy Schubert 			bss->ieee80211w = 1;
36804bc52338SCy Schubert #endif /* CONFIG_OCV */
3681e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ieee80211n") == 0) {
3682e28a4053SRui Paulo 		conf->ieee80211n = atoi(pos);
3683e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ht_capab") == 0) {
3684e28a4053SRui Paulo 		if (hostapd_config_ht_capab(conf, pos) < 0) {
36855b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab",
36865b9c547cSRui Paulo 				   line);
36875b9c547cSRui Paulo 			return 1;
3688e28a4053SRui Paulo 		}
3689f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "require_ht") == 0) {
3690f05cddf9SRui Paulo 		conf->require_ht = atoi(pos);
3691*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "ht_vht_twt_responder") == 0) {
3692*a90b9d01SCy Schubert 		conf->ht_vht_twt_responder = atoi(pos);
36935b9c547cSRui Paulo 	} else if (os_strcmp(buf, "obss_interval") == 0) {
36945b9c547cSRui Paulo 		conf->obss_interval = atoi(pos);
3695f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211AC
3696f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "ieee80211ac") == 0) {
3697f05cddf9SRui Paulo 		conf->ieee80211ac = atoi(pos);
3698f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "vht_capab") == 0) {
3699f05cddf9SRui Paulo 		if (hostapd_config_vht_capab(conf, pos) < 0) {
37005b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab",
37015b9c547cSRui Paulo 				   line);
37025b9c547cSRui Paulo 			return 1;
3703f05cddf9SRui Paulo 		}
3704f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "require_vht") == 0) {
3705f05cddf9SRui Paulo 		conf->require_vht = atoi(pos);
3706f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
3707f05cddf9SRui Paulo 		conf->vht_oper_chwidth = atoi(pos);
37085b9c547cSRui Paulo 	} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
3709f05cddf9SRui Paulo 		conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
37105b9c547cSRui Paulo 	} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) {
3711f05cddf9SRui Paulo 		conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
37125b9c547cSRui Paulo 	} else if (os_strcmp(buf, "vendor_vht") == 0) {
37135b9c547cSRui Paulo 		bss->vendor_vht = atoi(pos);
3714780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "use_sta_nsts") == 0) {
3715780fb4a2SCy Schubert 		bss->use_sta_nsts = atoi(pos);
3716f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211AC */
371785732ac8SCy Schubert #ifdef CONFIG_IEEE80211AX
371885732ac8SCy Schubert 	} else if (os_strcmp(buf, "ieee80211ax") == 0) {
371985732ac8SCy Schubert 		conf->ieee80211ax = atoi(pos);
3720*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "require_he") == 0) {
3721*a90b9d01SCy Schubert 		conf->require_he = atoi(pos);
372285732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_su_beamformer") == 0) {
372385732ac8SCy Schubert 		conf->he_phy_capab.he_su_beamformer = atoi(pos);
372485732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_su_beamformee") == 0) {
372585732ac8SCy Schubert 		conf->he_phy_capab.he_su_beamformee = atoi(pos);
372685732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
372785732ac8SCy Schubert 		conf->he_phy_capab.he_mu_beamformer = atoi(pos);
372885732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_bss_color") == 0) {
3729c1d255d3SCy Schubert 		conf->he_op.he_bss_color = atoi(pos) & 0x3f;
3730c1d255d3SCy Schubert 		conf->he_op.he_bss_color_disabled = 0;
3731c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
3732c1d255d3SCy Schubert 		conf->he_op.he_bss_color_partial = atoi(pos);
373385732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
373485732ac8SCy Schubert 		conf->he_op.he_default_pe_duration = atoi(pos);
373585732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_twt_required") == 0) {
373685732ac8SCy Schubert 		conf->he_op.he_twt_required = atoi(pos);
3737c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_twt_responder") == 0) {
3738c1d255d3SCy Schubert 		conf->he_op.he_twt_responder = atoi(pos);
373985732ac8SCy Schubert 	} else if (os_strcmp(buf, "he_rts_threshold") == 0) {
374085732ac8SCy Schubert 		conf->he_op.he_rts_threshold = atoi(pos);
37414b72b91aSCy Schubert 	} else if (os_strcmp(buf, "he_er_su_disable") == 0) {
37424b72b91aSCy Schubert 		conf->he_op.he_er_su_disable = atoi(pos);
3743206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) {
3744206b73d0SCy Schubert 		conf->he_op.he_basic_mcs_nss_set = atoi(pos);
37454bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) {
37464bc52338SCy Schubert 		conf->he_mu_edca.he_qos_info |=
37474bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_QOS_INFO_EDCA_PARAM_SET_COUNT);
37484bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_q_ack") == 0) {
37494bc52338SCy Schubert 		conf->he_mu_edca.he_qos_info |=
37504bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_QOS_INFO_Q_ACK);
37514bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_queue_request") == 0) {
37524bc52338SCy Schubert 		conf->he_mu_edca.he_qos_info |=
37534bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_QOS_INFO_QUEUE_REQUEST);
37544bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_txop_request") == 0) {
37554bc52338SCy Schubert 		conf->he_mu_edca.he_qos_info |=
37564bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_QOS_INFO_TXOP_REQUEST);
37574bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_aifsn") == 0) {
37584bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
37594bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
37604bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_acm") == 0) {
37614bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
37624bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
37634bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_aci") == 0) {
37644bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
37654bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
37664bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmin") == 0) {
37674bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
37684bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
37694bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmax") == 0) {
37704bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
37714bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
37724bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_timer") == 0) {
37734bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] =
37744bc52338SCy Schubert 			atoi(pos) & 0xff;
37754bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_aifsn") == 0) {
37764bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
37774bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
37784bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_acm") == 0) {
37794bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
37804bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
37814bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_aci") == 0) {
37824bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
37834bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
37844bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmin") == 0) {
37854bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
37864bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
37874bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmax") == 0) {
37884bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
37894bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
37904bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_timer") == 0) {
37914bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] =
37924bc52338SCy Schubert 			atoi(pos) & 0xff;
37934bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_aifsn") == 0) {
37944bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
37954bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
37964bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_acm") == 0) {
37974bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
37984bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
37994bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_aci") == 0) {
38004bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
38014bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
38024bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmin") == 0) {
38034bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
38044bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
38054bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmax") == 0) {
38064bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
38074bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
38084bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_timer") == 0) {
38094bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] =
38104bc52338SCy Schubert 			atoi(pos) & 0xff;
38114bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_aifsn") == 0) {
38124bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
38134bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
38144bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_acm") == 0) {
38154bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
38164bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
38174bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_aci") == 0) {
38184bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
38194bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
38204bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmin") == 0) {
38214bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
38224bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
38234bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmax") == 0) {
38244bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
38254bc52338SCy Schubert 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
38264bc52338SCy Schubert 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) {
38274bc52338SCy Schubert 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] =
38284bc52338SCy Schubert 			atoi(pos) & 0xff;
3829206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_spr_sr_control") == 0) {
3830c1d255d3SCy Schubert 		conf->spr.sr_control = atoi(pos) & 0x1f;
3831206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) {
3832206b73d0SCy Schubert 		conf->spr.non_srg_obss_pd_max_offset = atoi(pos);
3833206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) {
3834206b73d0SCy Schubert 		conf->spr.srg_obss_pd_min_offset = atoi(pos);
3835206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) {
3836206b73d0SCy Schubert 		conf->spr.srg_obss_pd_max_offset = atoi(pos);
3837c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_spr_srg_bss_colors") == 0) {
3838c1d255d3SCy Schubert 		if (hostapd_parse_he_srg_bitmap(
3839c1d255d3SCy Schubert 			conf->spr.srg_bss_color_bitmap, pos)) {
3840c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
3841c1d255d3SCy Schubert 				   "Line %d: Invalid srg bss colors list '%s'",
3842c1d255d3SCy Schubert 				   line, pos);
3843c1d255d3SCy Schubert 			return 1;
3844c1d255d3SCy Schubert 		}
3845c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_spr_srg_partial_bssid") == 0) {
3846c1d255d3SCy Schubert 		if (hostapd_parse_he_srg_bitmap(
3847c1d255d3SCy Schubert 			conf->spr.srg_partial_bssid_bitmap, pos)) {
3848c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
3849c1d255d3SCy Schubert 				   "Line %d: Invalid srg partial bssid list '%s'",
3850c1d255d3SCy Schubert 				   line, pos);
3851c1d255d3SCy Schubert 			return 1;
3852c1d255d3SCy Schubert 		}
3853*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) {
3854*a90b9d01SCy Schubert 		conf->he_6ghz_reg_pwr_type = atoi(pos);
3855*a90b9d01SCy Schubert 		if (conf->he_6ghz_reg_pwr_type > HE_REG_INFO_6GHZ_AP_TYPE_MAX) {
3856*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
3857*a90b9d01SCy Schubert 				   "Line %d: invalid he_6ghz_reg_pwr_type value",
3858*a90b9d01SCy Schubert 				   line);
3859*a90b9d01SCy Schubert 			return 1;
3860*a90b9d01SCy Schubert 		}
3861*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "reg_def_cli_eirp_psd") == 0) {
3862*a90b9d01SCy Schubert 		conf->reg_def_cli_eirp_psd = atoi(pos);
3863*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "reg_sub_cli_eirp_psd") == 0) {
3864*a90b9d01SCy Schubert 		conf->reg_sub_cli_eirp_psd = atoi(pos);
3865*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "reg_def_cli_eirp") == 0) {
3866*a90b9d01SCy Schubert 		conf->reg_def_cli_eirp = atoi(pos);
3867206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
3868206b73d0SCy Schubert 		conf->he_oper_chwidth = atoi(pos);
3869206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
3870206b73d0SCy Schubert 		conf->he_oper_centr_freq_seg0_idx = atoi(pos);
3871206b73d0SCy Schubert 	} else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) {
3872206b73d0SCy Schubert 		conf->he_oper_centr_freq_seg1_idx = atoi(pos);
3873c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_6ghz_max_mpdu") == 0) {
3874c1d255d3SCy Schubert 		conf->he_6ghz_max_mpdu = atoi(pos);
3875c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_6ghz_max_ampdu_len_exp") == 0) {
3876c1d255d3SCy Schubert 		conf->he_6ghz_max_ampdu_len_exp = atoi(pos);
3877c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_6ghz_rx_ant_pat") == 0) {
3878c1d255d3SCy Schubert 		conf->he_6ghz_rx_ant_pat = atoi(pos);
3879c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "he_6ghz_tx_ant_pat") == 0) {
3880c1d255d3SCy Schubert 		conf->he_6ghz_tx_ant_pat = atoi(pos);
3881c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "unsol_bcast_probe_resp_interval") == 0) {
3882c1d255d3SCy Schubert 		int val = atoi(pos);
3883c1d255d3SCy Schubert 
3884c1d255d3SCy Schubert 		if (val < 0 || val > 20) {
3885c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
3886c1d255d3SCy Schubert 				   "Line %d: invalid unsol_bcast_probe_resp_interval value",
3887c1d255d3SCy Schubert 				   line);
3888c1d255d3SCy Schubert 			return 1;
3889c1d255d3SCy Schubert 		}
3890c1d255d3SCy Schubert 		bss->unsol_bcast_probe_resp_interval = val;
3891*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "mbssid") == 0) {
3892*a90b9d01SCy Schubert 		int mbssid = atoi(pos);
3893*a90b9d01SCy Schubert 		if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
3894*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
3895*a90b9d01SCy Schubert 				   "Line %d: invalid mbssid (%d): '%s'.",
3896*a90b9d01SCy Schubert 				   line, mbssid, pos);
3897*a90b9d01SCy Schubert 			return 1;
3898*a90b9d01SCy Schubert 		}
3899*a90b9d01SCy Schubert 		conf->mbssid = mbssid;
390085732ac8SCy Schubert #endif /* CONFIG_IEEE80211AX */
3901e28a4053SRui Paulo 	} else if (os_strcmp(buf, "max_listen_interval") == 0) {
3902e28a4053SRui Paulo 		bss->max_listen_interval = atoi(pos);
3903f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
3904f05cddf9SRui Paulo 		bss->disable_pmksa_caching = atoi(pos);
3905e28a4053SRui Paulo 	} else if (os_strcmp(buf, "okc") == 0) {
3906e28a4053SRui Paulo 		bss->okc = atoi(pos);
3907e28a4053SRui Paulo #ifdef CONFIG_WPS
3908e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wps_state") == 0) {
3909e28a4053SRui Paulo 		bss->wps_state = atoi(pos);
3910e28a4053SRui Paulo 		if (bss->wps_state < 0 || bss->wps_state > 2) {
39115b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid wps_state",
39125b9c547cSRui Paulo 				   line);
39135b9c547cSRui Paulo 			return 1;
3914e28a4053SRui Paulo 		}
39155b9c547cSRui Paulo 	} else if (os_strcmp(buf, "wps_independent") == 0) {
39165b9c547cSRui Paulo 		bss->wps_independent = atoi(pos);
3917e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ap_setup_locked") == 0) {
3918e28a4053SRui Paulo 		bss->ap_setup_locked = atoi(pos);
3919e28a4053SRui Paulo 	} else if (os_strcmp(buf, "uuid") == 0) {
3920e28a4053SRui Paulo 		if (uuid_str2bin(pos, bss->uuid)) {
39215b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
39225b9c547cSRui Paulo 			return 1;
3923e28a4053SRui Paulo 		}
3924e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wps_pin_requests") == 0) {
3925e28a4053SRui Paulo 		os_free(bss->wps_pin_requests);
3926e28a4053SRui Paulo 		bss->wps_pin_requests = os_strdup(pos);
3927e28a4053SRui Paulo 	} else if (os_strcmp(buf, "device_name") == 0) {
3928325151a3SRui Paulo 		if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) {
3929e28a4053SRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Too long "
3930e28a4053SRui Paulo 				   "device_name", line);
39315b9c547cSRui Paulo 			return 1;
3932e28a4053SRui Paulo 		}
3933e28a4053SRui Paulo 		os_free(bss->device_name);
3934e28a4053SRui Paulo 		bss->device_name = os_strdup(pos);
3935e28a4053SRui Paulo 	} else if (os_strcmp(buf, "manufacturer") == 0) {
3936e28a4053SRui Paulo 		if (os_strlen(pos) > 64) {
39375b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer",
39385b9c547cSRui Paulo 				   line);
39395b9c547cSRui Paulo 			return 1;
3940e28a4053SRui Paulo 		}
3941e28a4053SRui Paulo 		os_free(bss->manufacturer);
3942e28a4053SRui Paulo 		bss->manufacturer = os_strdup(pos);
3943e28a4053SRui Paulo 	} else if (os_strcmp(buf, "model_name") == 0) {
3944e28a4053SRui Paulo 		if (os_strlen(pos) > 32) {
39455b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Too long model_name",
39465b9c547cSRui Paulo 				   line);
39475b9c547cSRui Paulo 			return 1;
3948e28a4053SRui Paulo 		}
3949e28a4053SRui Paulo 		os_free(bss->model_name);
3950e28a4053SRui Paulo 		bss->model_name = os_strdup(pos);
3951e28a4053SRui Paulo 	} else if (os_strcmp(buf, "model_number") == 0) {
3952e28a4053SRui Paulo 		if (os_strlen(pos) > 32) {
39535b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Too long model_number",
39545b9c547cSRui Paulo 				   line);
39555b9c547cSRui Paulo 			return 1;
3956e28a4053SRui Paulo 		}
3957e28a4053SRui Paulo 		os_free(bss->model_number);
3958e28a4053SRui Paulo 		bss->model_number = os_strdup(pos);
3959e28a4053SRui Paulo 	} else if (os_strcmp(buf, "serial_number") == 0) {
3960e28a4053SRui Paulo 		if (os_strlen(pos) > 32) {
39615b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Too long serial_number",
39625b9c547cSRui Paulo 				   line);
39635b9c547cSRui Paulo 			return 1;
3964e28a4053SRui Paulo 		}
3965e28a4053SRui Paulo 		os_free(bss->serial_number);
3966e28a4053SRui Paulo 		bss->serial_number = os_strdup(pos);
3967e28a4053SRui Paulo 	} else if (os_strcmp(buf, "device_type") == 0) {
3968f05cddf9SRui Paulo 		if (wps_dev_type_str2bin(pos, bss->device_type))
39695b9c547cSRui Paulo 			return 1;
3970e28a4053SRui Paulo 	} else if (os_strcmp(buf, "config_methods") == 0) {
3971e28a4053SRui Paulo 		os_free(bss->config_methods);
3972e28a4053SRui Paulo 		bss->config_methods = os_strdup(pos);
3973e28a4053SRui Paulo 	} else if (os_strcmp(buf, "os_version") == 0) {
3974e28a4053SRui Paulo 		if (hexstr2bin(pos, bss->os_version, 4)) {
39755b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid os_version",
39765b9c547cSRui Paulo 				   line);
39775b9c547cSRui Paulo 			return 1;
3978e28a4053SRui Paulo 		}
3979e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ap_pin") == 0) {
3980e28a4053SRui Paulo 		os_free(bss->ap_pin);
398185732ac8SCy Schubert 		if (*pos == '\0')
398285732ac8SCy Schubert 			bss->ap_pin = NULL;
398385732ac8SCy Schubert 		else
3984e28a4053SRui Paulo 			bss->ap_pin = os_strdup(pos);
3985e28a4053SRui Paulo 	} else if (os_strcmp(buf, "skip_cred_build") == 0) {
3986e28a4053SRui Paulo 		bss->skip_cred_build = atoi(pos);
3987e28a4053SRui Paulo 	} else if (os_strcmp(buf, "extra_cred") == 0) {
3988e28a4053SRui Paulo 		os_free(bss->extra_cred);
39895b9c547cSRui Paulo 		bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len);
3990e28a4053SRui Paulo 		if (bss->extra_cred == NULL) {
39915b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'",
3992e28a4053SRui Paulo 				   line, pos);
39935b9c547cSRui Paulo 			return 1;
3994e28a4053SRui Paulo 		}
3995e28a4053SRui Paulo 	} else if (os_strcmp(buf, "wps_cred_processing") == 0) {
3996e28a4053SRui Paulo 		bss->wps_cred_processing = atoi(pos);
39974bc52338SCy Schubert 	} else if (os_strcmp(buf, "wps_cred_add_sae") == 0) {
39984bc52338SCy Schubert 		bss->wps_cred_add_sae = atoi(pos);
3999e28a4053SRui Paulo 	} else if (os_strcmp(buf, "ap_settings") == 0) {
4000e28a4053SRui Paulo 		os_free(bss->ap_settings);
4001e28a4053SRui Paulo 		bss->ap_settings =
4002e28a4053SRui Paulo 			(u8 *) os_readfile(pos, &bss->ap_settings_len);
4003e28a4053SRui Paulo 		if (bss->ap_settings == NULL) {
40045b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'",
4005e28a4053SRui Paulo 				   line, pos);
40065b9c547cSRui Paulo 			return 1;
4007e28a4053SRui Paulo 		}
40084bc52338SCy Schubert 	} else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) {
40094bc52338SCy Schubert 		size_t slen;
40104bc52338SCy Schubert 		char *str = wpa_config_parse_string(pos, &slen);
40114bc52338SCy Schubert 
40124bc52338SCy Schubert 		if (!str || slen < 1 || slen > SSID_MAX_LEN) {
40134bc52338SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
40144bc52338SCy Schubert 				   line, pos);
40154bc52338SCy Schubert 			os_free(str);
40164bc52338SCy Schubert 			return 1;
40174bc52338SCy Schubert 		}
40184bc52338SCy Schubert 		os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen);
40194bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.ssid_len = slen;
40204bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.ssid_set = 1;
40214bc52338SCy Schubert 		os_free(str);
40224bc52338SCy Schubert 	} else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) {
40234bc52338SCy Schubert 		int len = os_strlen(pos);
40244bc52338SCy Schubert 
40254bc52338SCy Schubert 		if (len < 8 || len > 63) {
40264bc52338SCy Schubert 			wpa_printf(MSG_ERROR,
40274bc52338SCy Schubert 				   "Line %d: invalid WPA passphrase length %d (expected 8..63)",
40284bc52338SCy Schubert 				   line, len);
40294bc52338SCy Schubert 			return 1;
40304bc52338SCy Schubert 		}
40314bc52338SCy Schubert 		os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
40324bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos);
40334bc52338SCy Schubert 		if (bss->multi_ap_backhaul_ssid.wpa_passphrase) {
40344bc52338SCy Schubert 			hostapd_config_clear_wpa_psk(
40354bc52338SCy Schubert 				&bss->multi_ap_backhaul_ssid.wpa_psk);
40364bc52338SCy Schubert 			bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1;
40374bc52338SCy Schubert 		}
40384bc52338SCy Schubert 	} else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) {
40394bc52338SCy Schubert 		hostapd_config_clear_wpa_psk(
40404bc52338SCy Schubert 			&bss->multi_ap_backhaul_ssid.wpa_psk);
40414bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.wpa_psk =
40424bc52338SCy Schubert 			os_zalloc(sizeof(struct hostapd_wpa_psk));
40434bc52338SCy Schubert 		if (!bss->multi_ap_backhaul_ssid.wpa_psk)
40444bc52338SCy Schubert 			return 1;
40454bc52338SCy Schubert 		if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk,
40464bc52338SCy Schubert 			       PMK_LEN) ||
40474bc52338SCy Schubert 		    pos[PMK_LEN * 2] != '\0') {
40484bc52338SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
40494bc52338SCy Schubert 				   line, pos);
40504bc52338SCy Schubert 			hostapd_config_clear_wpa_psk(
40514bc52338SCy Schubert 				&bss->multi_ap_backhaul_ssid.wpa_psk);
40524bc52338SCy Schubert 			return 1;
40534bc52338SCy Schubert 		}
40544bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.wpa_psk->group = 1;
40554bc52338SCy Schubert 		os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
40564bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL;
40574bc52338SCy Schubert 		bss->multi_ap_backhaul_ssid.wpa_psk_set = 1;
4058e28a4053SRui Paulo 	} else if (os_strcmp(buf, "upnp_iface") == 0) {
40595b9c547cSRui Paulo 		os_free(bss->upnp_iface);
4060e28a4053SRui Paulo 		bss->upnp_iface = os_strdup(pos);
4061e28a4053SRui Paulo 	} else if (os_strcmp(buf, "friendly_name") == 0) {
4062e28a4053SRui Paulo 		os_free(bss->friendly_name);
4063e28a4053SRui Paulo 		bss->friendly_name = os_strdup(pos);
4064e28a4053SRui Paulo 	} else if (os_strcmp(buf, "manufacturer_url") == 0) {
4065e28a4053SRui Paulo 		os_free(bss->manufacturer_url);
4066e28a4053SRui Paulo 		bss->manufacturer_url = os_strdup(pos);
4067e28a4053SRui Paulo 	} else if (os_strcmp(buf, "model_description") == 0) {
4068e28a4053SRui Paulo 		os_free(bss->model_description);
4069e28a4053SRui Paulo 		bss->model_description = os_strdup(pos);
4070e28a4053SRui Paulo 	} else if (os_strcmp(buf, "model_url") == 0) {
4071e28a4053SRui Paulo 		os_free(bss->model_url);
4072e28a4053SRui Paulo 		bss->model_url = os_strdup(pos);
4073e28a4053SRui Paulo 	} else if (os_strcmp(buf, "upc") == 0) {
4074e28a4053SRui Paulo 		os_free(bss->upc);
4075e28a4053SRui Paulo 		bss->upc = os_strdup(pos);
4076f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
4077f05cddf9SRui Paulo 		bss->pbc_in_m1 = atoi(pos);
40785b9c547cSRui Paulo 	} else if (os_strcmp(buf, "server_id") == 0) {
40795b9c547cSRui Paulo 		os_free(bss->server_id);
40805b9c547cSRui Paulo 		bss->server_id = os_strdup(pos);
4081c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "wps_application_ext") == 0) {
4082c1d255d3SCy Schubert 		wpabuf_free(bss->wps_application_ext);
4083c1d255d3SCy Schubert 		bss->wps_application_ext = wpabuf_parse_bin(pos);
4084f05cddf9SRui Paulo #ifdef CONFIG_WPS_NFC
4085f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
4086f05cddf9SRui Paulo 		bss->wps_nfc_dev_pw_id = atoi(pos);
4087f05cddf9SRui Paulo 		if (bss->wps_nfc_dev_pw_id < 0x10 ||
4088f05cddf9SRui Paulo 		    bss->wps_nfc_dev_pw_id > 0xffff) {
40895b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value",
40905b9c547cSRui Paulo 				   line);
40915b9c547cSRui Paulo 			return 1;
4092f05cddf9SRui Paulo 		}
40935b9c547cSRui Paulo 		bss->wps_nfc_pw_from_config = 1;
4094f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
4095f05cddf9SRui Paulo 		wpabuf_free(bss->wps_nfc_dh_pubkey);
4096780fb4a2SCy Schubert 		bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos);
40975b9c547cSRui Paulo 		bss->wps_nfc_pw_from_config = 1;
4098f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
4099f05cddf9SRui Paulo 		wpabuf_free(bss->wps_nfc_dh_privkey);
4100780fb4a2SCy Schubert 		bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos);
41015b9c547cSRui Paulo 		bss->wps_nfc_pw_from_config = 1;
4102f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
4103f05cddf9SRui Paulo 		wpabuf_free(bss->wps_nfc_dev_pw);
4104780fb4a2SCy Schubert 		bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos);
41055b9c547cSRui Paulo 		bss->wps_nfc_pw_from_config = 1;
4106f05cddf9SRui Paulo #endif /* CONFIG_WPS_NFC */
4107e28a4053SRui Paulo #endif /* CONFIG_WPS */
4108f05cddf9SRui Paulo #ifdef CONFIG_P2P_MANAGER
4109f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "manage_p2p") == 0) {
41105b9c547cSRui Paulo 		if (atoi(pos))
4111f05cddf9SRui Paulo 			bss->p2p |= P2P_MANAGE;
4112f05cddf9SRui Paulo 		else
4113f05cddf9SRui Paulo 			bss->p2p &= ~P2P_MANAGE;
4114f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "allow_cross_connection") == 0) {
4115f05cddf9SRui Paulo 		if (atoi(pos))
4116f05cddf9SRui Paulo 			bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
4117f05cddf9SRui Paulo 		else
4118f05cddf9SRui Paulo 			bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
4119f05cddf9SRui Paulo #endif /* CONFIG_P2P_MANAGER */
4120f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
4121f05cddf9SRui Paulo 		bss->disassoc_low_ack = atoi(pos);
4122f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "tdls_prohibit") == 0) {
41235b9c547cSRui Paulo 		if (atoi(pos))
4124f05cddf9SRui Paulo 			bss->tdls |= TDLS_PROHIBIT;
4125f05cddf9SRui Paulo 		else
4126f05cddf9SRui Paulo 			bss->tdls &= ~TDLS_PROHIBIT;
4127f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
41285b9c547cSRui Paulo 		if (atoi(pos))
4129f05cddf9SRui Paulo 			bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
4130f05cddf9SRui Paulo 		else
4131f05cddf9SRui Paulo 			bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
4132f05cddf9SRui Paulo #ifdef CONFIG_RSN_TESTING
4133f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "rsn_testing") == 0) {
4134f05cddf9SRui Paulo 		extern int rsn_testing;
4135f05cddf9SRui Paulo 		rsn_testing = atoi(pos);
4136f05cddf9SRui Paulo #endif /* CONFIG_RSN_TESTING */
4137f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "time_advertisement") == 0) {
4138f05cddf9SRui Paulo 		bss->time_advertisement = atoi(pos);
4139f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "time_zone") == 0) {
4140f05cddf9SRui Paulo 		size_t tz_len = os_strlen(pos);
4141f05cddf9SRui Paulo 		if (tz_len < 4 || tz_len > 255) {
41425b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone",
41435b9c547cSRui Paulo 				   line);
41445b9c547cSRui Paulo 			return 1;
4145f05cddf9SRui Paulo 		}
4146f05cddf9SRui Paulo 		os_free(bss->time_zone);
4147f05cddf9SRui Paulo 		bss->time_zone = os_strdup(pos);
4148f05cddf9SRui Paulo 		if (bss->time_zone == NULL)
41495b9c547cSRui Paulo 			return 1;
415085732ac8SCy Schubert #ifdef CONFIG_WNM_AP
4151f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
4152f05cddf9SRui Paulo 		bss->wnm_sleep_mode = atoi(pos);
415385732ac8SCy Schubert 	} else if (os_strcmp(buf, "wnm_sleep_mode_no_keys") == 0) {
415485732ac8SCy Schubert 		bss->wnm_sleep_mode_no_keys = atoi(pos);
4155f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "bss_transition") == 0) {
4156f05cddf9SRui Paulo 		bss->bss_transition = atoi(pos);
415785732ac8SCy Schubert #endif /* CONFIG_WNM_AP */
4158f05cddf9SRui Paulo #ifdef CONFIG_INTERWORKING
4159f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "interworking") == 0) {
4160f05cddf9SRui Paulo 		bss->interworking = atoi(pos);
4161f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "access_network_type") == 0) {
4162f05cddf9SRui Paulo 		bss->access_network_type = atoi(pos);
4163f05cddf9SRui Paulo 		if (bss->access_network_type < 0 ||
4164f05cddf9SRui Paulo 		    bss->access_network_type > 15) {
41655b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
41665b9c547cSRui Paulo 				   "Line %d: invalid access_network_type",
41675b9c547cSRui Paulo 				   line);
41685b9c547cSRui Paulo 			return 1;
4169f05cddf9SRui Paulo 		}
4170f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "internet") == 0) {
4171f05cddf9SRui Paulo 		bss->internet = atoi(pos);
4172f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "asra") == 0) {
4173f05cddf9SRui Paulo 		bss->asra = atoi(pos);
4174f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "esr") == 0) {
4175f05cddf9SRui Paulo 		bss->esr = atoi(pos);
4176f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "uesa") == 0) {
4177f05cddf9SRui Paulo 		bss->uesa = atoi(pos);
4178f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "venue_group") == 0) {
4179f05cddf9SRui Paulo 		bss->venue_group = atoi(pos);
4180f05cddf9SRui Paulo 		bss->venue_info_set = 1;
4181f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "venue_type") == 0) {
4182f05cddf9SRui Paulo 		bss->venue_type = atoi(pos);
4183f05cddf9SRui Paulo 		bss->venue_info_set = 1;
4184f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "hessid") == 0) {
4185f05cddf9SRui Paulo 		if (hwaddr_aton(pos, bss->hessid)) {
41865b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line);
41875b9c547cSRui Paulo 			return 1;
4188f05cddf9SRui Paulo 		}
4189f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "roaming_consortium") == 0) {
4190f05cddf9SRui Paulo 		if (parse_roaming_consortium(bss, pos, line) < 0)
41915b9c547cSRui Paulo 			return 1;
4192f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "venue_name") == 0) {
4193f05cddf9SRui Paulo 		if (parse_venue_name(bss, pos, line) < 0)
41945b9c547cSRui Paulo 			return 1;
419585732ac8SCy Schubert 	} else if (os_strcmp(buf, "venue_url") == 0) {
419685732ac8SCy Schubert 		if (parse_venue_url(bss, pos, line) < 0)
419785732ac8SCy Schubert 			return 1;
4198f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "network_auth_type") == 0) {
4199f05cddf9SRui Paulo 		u8 auth_type;
4200f05cddf9SRui Paulo 		u16 redirect_url_len;
4201f05cddf9SRui Paulo 		if (hexstr2bin(pos, &auth_type, 1)) {
42025b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
42035b9c547cSRui Paulo 				   "Line %d: Invalid network_auth_type '%s'",
4204f05cddf9SRui Paulo 				   line, pos);
42055b9c547cSRui Paulo 			return 1;
4206f05cddf9SRui Paulo 		}
4207f05cddf9SRui Paulo 		if (auth_type == 0 || auth_type == 2)
4208f05cddf9SRui Paulo 			redirect_url_len = os_strlen(pos + 2);
4209f05cddf9SRui Paulo 		else
4210f05cddf9SRui Paulo 			redirect_url_len = 0;
4211f05cddf9SRui Paulo 		os_free(bss->network_auth_type);
42125b9c547cSRui Paulo 		bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1);
42135b9c547cSRui Paulo 		if (bss->network_auth_type == NULL)
42145b9c547cSRui Paulo 			return 1;
4215f05cddf9SRui Paulo 		*bss->network_auth_type = auth_type;
42165b9c547cSRui Paulo 		WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len);
4217f05cddf9SRui Paulo 		if (redirect_url_len)
42185b9c547cSRui Paulo 			os_memcpy(bss->network_auth_type + 3, pos + 2,
42195b9c547cSRui Paulo 				  redirect_url_len);
4220f05cddf9SRui Paulo 		bss->network_auth_type_len = 3 + redirect_url_len;
4221f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
42225b9c547cSRui Paulo 		if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) {
42235b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'",
4224f05cddf9SRui Paulo 				   line, pos);
4225f05cddf9SRui Paulo 			bss->ipaddr_type_configured = 0;
42265b9c547cSRui Paulo 			return 1;
4227f05cddf9SRui Paulo 		}
4228f05cddf9SRui Paulo 		bss->ipaddr_type_configured = 1;
4229f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "domain_name") == 0) {
4230f05cddf9SRui Paulo 		int j, num_domains, domain_len, domain_list_len = 0;
4231f05cddf9SRui Paulo 		char *tok_start, *tok_prev;
4232f05cddf9SRui Paulo 		u8 *domain_list, *domain_ptr;
4233f05cddf9SRui Paulo 
4234f05cddf9SRui Paulo 		domain_list_len = os_strlen(pos) + 1;
4235f05cddf9SRui Paulo 		domain_list = os_malloc(domain_list_len);
42365b9c547cSRui Paulo 		if (domain_list == NULL)
42375b9c547cSRui Paulo 			return 1;
4238f05cddf9SRui Paulo 
4239f05cddf9SRui Paulo 		domain_ptr = domain_list;
4240f05cddf9SRui Paulo 		tok_prev = pos;
4241f05cddf9SRui Paulo 		num_domains = 1;
4242f05cddf9SRui Paulo 		while ((tok_prev = os_strchr(tok_prev, ','))) {
4243f05cddf9SRui Paulo 			num_domains++;
4244f05cddf9SRui Paulo 			tok_prev++;
4245f05cddf9SRui Paulo 		}
4246f05cddf9SRui Paulo 		tok_prev = pos;
4247f05cddf9SRui Paulo 		for (j = 0; j < num_domains; j++) {
4248f05cddf9SRui Paulo 			tok_start = os_strchr(tok_prev, ',');
4249f05cddf9SRui Paulo 			if (tok_start) {
4250f05cddf9SRui Paulo 				domain_len = tok_start - tok_prev;
4251f05cddf9SRui Paulo 				*domain_ptr = domain_len;
42525b9c547cSRui Paulo 				os_memcpy(domain_ptr + 1, tok_prev, domain_len);
4253f05cddf9SRui Paulo 				domain_ptr += domain_len + 1;
4254f05cddf9SRui Paulo 				tok_prev = ++tok_start;
4255f05cddf9SRui Paulo 			} else {
4256f05cddf9SRui Paulo 				domain_len = os_strlen(tok_prev);
4257f05cddf9SRui Paulo 				*domain_ptr = domain_len;
42585b9c547cSRui Paulo 				os_memcpy(domain_ptr + 1, tok_prev, domain_len);
4259f05cddf9SRui Paulo 				domain_ptr += domain_len + 1;
4260f05cddf9SRui Paulo 			}
4261f05cddf9SRui Paulo 		}
4262f05cddf9SRui Paulo 
4263f05cddf9SRui Paulo 		os_free(bss->domain_name);
4264f05cddf9SRui Paulo 		bss->domain_name = domain_list;
4265f05cddf9SRui Paulo 		bss->domain_name_len = domain_list_len;
4266f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
4267f05cddf9SRui Paulo 		if (parse_3gpp_cell_net(bss, pos, line) < 0)
42685b9c547cSRui Paulo 			return 1;
4269f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "nai_realm") == 0) {
4270f05cddf9SRui Paulo 		if (parse_nai_realm(bss, pos, line) < 0)
42715b9c547cSRui Paulo 			return 1;
4272780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "anqp_elem") == 0) {
4273780fb4a2SCy Schubert 		if (parse_anqp_elem(bss, pos, line) < 0)
4274780fb4a2SCy Schubert 			return 1;
4275f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "gas_frag_limit") == 0) {
427685732ac8SCy Schubert 		int val = atoi(pos);
427785732ac8SCy Schubert 
427885732ac8SCy Schubert 		if (val <= 0) {
427985732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
428085732ac8SCy Schubert 				   "Line %d: Invalid gas_frag_limit '%s'",
428185732ac8SCy Schubert 				   line, pos);
428285732ac8SCy Schubert 			return 1;
428385732ac8SCy Schubert 		}
428485732ac8SCy Schubert 		bss->gas_frag_limit = val;
4285f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
4286f05cddf9SRui Paulo 		bss->gas_comeback_delay = atoi(pos);
4287*a90b9d01SCy Schubert #endif /* CONFIG_INTERWORKING */
42885b9c547cSRui Paulo 	} else if (os_strcmp(buf, "qos_map_set") == 0) {
42895b9c547cSRui Paulo 		if (parse_qos_map_set(bss, pos, line) < 0)
42905b9c547cSRui Paulo 			return 1;
4291f05cddf9SRui Paulo #ifdef CONFIG_RADIUS_TEST
4292f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "dump_msk_file") == 0) {
4293f05cddf9SRui Paulo 		os_free(bss->dump_msk_file);
4294f05cddf9SRui Paulo 		bss->dump_msk_file = os_strdup(pos);
4295f05cddf9SRui Paulo #endif /* CONFIG_RADIUS_TEST */
4296780fb4a2SCy Schubert #ifdef CONFIG_PROXYARP
4297780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "proxy_arp") == 0) {
4298780fb4a2SCy Schubert 		bss->proxy_arp = atoi(pos);
4299780fb4a2SCy Schubert #endif /* CONFIG_PROXYARP */
4300f05cddf9SRui Paulo #ifdef CONFIG_HS20
4301f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "hs20") == 0) {
4302f05cddf9SRui Paulo 		bss->hs20 = atoi(pos);
43034bc52338SCy Schubert 	} else if (os_strcmp(buf, "hs20_release") == 0) {
43044bc52338SCy Schubert 		int val = atoi(pos);
43054bc52338SCy Schubert 
43064bc52338SCy Schubert 		if (val < 1 || val > (HS20_VERSION >> 4) + 1) {
43074bc52338SCy Schubert 			wpa_printf(MSG_ERROR,
43084bc52338SCy Schubert 				   "Line %d: Unsupported hs20_release: %s",
43094bc52338SCy Schubert 				   line, pos);
43104bc52338SCy Schubert 			return 1;
43114bc52338SCy Schubert 		}
43124bc52338SCy Schubert 		bss->hs20_release = val;
4313f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "disable_dgaf") == 0) {
4314f05cddf9SRui Paulo 		bss->disable_dgaf = atoi(pos);
4315325151a3SRui Paulo 	} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
4316325151a3SRui Paulo 		bss->na_mcast_to_ucast = atoi(pos);
43175b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osen") == 0) {
43185b9c547cSRui Paulo 		bss->osen = atoi(pos);
43195b9c547cSRui Paulo 	} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
43205b9c547cSRui Paulo 		bss->anqp_domain_id = atoi(pos);
43215b9c547cSRui Paulo 	} else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
43225b9c547cSRui Paulo 		bss->hs20_deauth_req_timeout = atoi(pos);
4323f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
4324f05cddf9SRui Paulo 		if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
43255b9c547cSRui Paulo 			return 1;
4326f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
43275b9c547cSRui Paulo 		if (hs20_parse_wan_metrics(bss, pos, line) < 0)
43285b9c547cSRui Paulo 			return 1;
4329f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
4330f05cddf9SRui Paulo 		if (hs20_parse_conn_capab(bss, pos, line) < 0) {
43315b9c547cSRui Paulo 			return 1;
4332f05cddf9SRui Paulo 		}
4333f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "hs20_operating_class") == 0) {
4334f05cddf9SRui Paulo 		u8 *oper_class;
4335f05cddf9SRui Paulo 		size_t oper_class_len;
4336f05cddf9SRui Paulo 		oper_class_len = os_strlen(pos);
4337f05cddf9SRui Paulo 		if (oper_class_len < 2 || (oper_class_len & 0x01)) {
43385b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
43395b9c547cSRui Paulo 				   "Line %d: Invalid hs20_operating_class '%s'",
4340f05cddf9SRui Paulo 				   line, pos);
43415b9c547cSRui Paulo 			return 1;
4342f05cddf9SRui Paulo 		}
4343f05cddf9SRui Paulo 		oper_class_len /= 2;
4344f05cddf9SRui Paulo 		oper_class = os_malloc(oper_class_len);
43455b9c547cSRui Paulo 		if (oper_class == NULL)
43465b9c547cSRui Paulo 			return 1;
4347f05cddf9SRui Paulo 		if (hexstr2bin(pos, oper_class, oper_class_len)) {
43485b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
43495b9c547cSRui Paulo 				   "Line %d: Invalid hs20_operating_class '%s'",
4350f05cddf9SRui Paulo 				   line, pos);
4351f05cddf9SRui Paulo 			os_free(oper_class);
43525b9c547cSRui Paulo 			return 1;
4353f05cddf9SRui Paulo 		}
4354f05cddf9SRui Paulo 		os_free(bss->hs20_operating_class);
4355f05cddf9SRui Paulo 		bss->hs20_operating_class = oper_class;
4356f05cddf9SRui Paulo 		bss->hs20_operating_class_len = oper_class_len;
43575b9c547cSRui Paulo 	} else if (os_strcmp(buf, "hs20_icon") == 0) {
43585b9c547cSRui Paulo 		if (hs20_parse_icon(bss, pos) < 0) {
43595b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
43605b9c547cSRui Paulo 				   line, pos);
43615b9c547cSRui Paulo 			return 1;
43625b9c547cSRui Paulo 		}
43635b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_ssid") == 0) {
43645b9c547cSRui Paulo 		if (hs20_parse_osu_ssid(bss, pos, line) < 0)
43655b9c547cSRui Paulo 			return 1;
43665b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_server_uri") == 0) {
43675b9c547cSRui Paulo 		if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
43685b9c547cSRui Paulo 			return 1;
43695b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_friendly_name") == 0) {
43705b9c547cSRui Paulo 		if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
43715b9c547cSRui Paulo 			return 1;
43725b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_nai") == 0) {
43735b9c547cSRui Paulo 		if (hs20_parse_osu_nai(bss, pos, line) < 0)
43745b9c547cSRui Paulo 			return 1;
437585732ac8SCy Schubert 	} else if (os_strcmp(buf, "osu_nai2") == 0) {
437685732ac8SCy Schubert 		if (hs20_parse_osu_nai2(bss, pos, line) < 0)
437785732ac8SCy Schubert 			return 1;
43785b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_method_list") == 0) {
43795b9c547cSRui Paulo 		if (hs20_parse_osu_method_list(bss, pos, line) < 0)
43805b9c547cSRui Paulo 			return 1;
43815b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_icon") == 0) {
43825b9c547cSRui Paulo 		if (hs20_parse_osu_icon(bss, pos, line) < 0)
43835b9c547cSRui Paulo 			return 1;
43845b9c547cSRui Paulo 	} else if (os_strcmp(buf, "osu_service_desc") == 0) {
43855b9c547cSRui Paulo 		if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
43865b9c547cSRui Paulo 			return 1;
438785732ac8SCy Schubert 	} else if (os_strcmp(buf, "operator_icon") == 0) {
438885732ac8SCy Schubert 		if (hs20_parse_operator_icon(bss, pos, line) < 0)
438985732ac8SCy Schubert 			return 1;
43905b9c547cSRui Paulo 	} else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
43915b9c547cSRui Paulo 		os_free(bss->subscr_remediation_url);
43925b9c547cSRui Paulo 		bss->subscr_remediation_url = os_strdup(pos);
43935b9c547cSRui Paulo 	} else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
43945b9c547cSRui Paulo 		bss->subscr_remediation_method = atoi(pos);
439585732ac8SCy Schubert 	} else if (os_strcmp(buf, "hs20_t_c_filename") == 0) {
439685732ac8SCy Schubert 		os_free(bss->t_c_filename);
439785732ac8SCy Schubert 		bss->t_c_filename = os_strdup(pos);
439885732ac8SCy Schubert 	} else if (os_strcmp(buf, "hs20_t_c_timestamp") == 0) {
439985732ac8SCy Schubert 		bss->t_c_timestamp = strtol(pos, NULL, 0);
440085732ac8SCy Schubert 	} else if (os_strcmp(buf, "hs20_t_c_server_url") == 0) {
440185732ac8SCy Schubert 		os_free(bss->t_c_server_url);
440285732ac8SCy Schubert 		bss->t_c_server_url = os_strdup(pos);
44034bc52338SCy Schubert 	} else if (os_strcmp(buf, "hs20_sim_provisioning_url") == 0) {
44044bc52338SCy Schubert 		os_free(bss->hs20_sim_provisioning_url);
44054bc52338SCy Schubert 		bss->hs20_sim_provisioning_url = os_strdup(pos);
4406f05cddf9SRui Paulo #endif /* CONFIG_HS20 */
4407780fb4a2SCy Schubert #ifdef CONFIG_MBO
4408780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "mbo") == 0) {
4409780fb4a2SCy Schubert 		bss->mbo_enabled = atoi(pos);
441085732ac8SCy Schubert 	} else if (os_strcmp(buf, "mbo_cell_data_conn_pref") == 0) {
441185732ac8SCy Schubert 		bss->mbo_cell_data_conn_pref = atoi(pos);
441285732ac8SCy Schubert 	} else if (os_strcmp(buf, "oce") == 0) {
441385732ac8SCy Schubert 		bss->oce = atoi(pos);
4414780fb4a2SCy Schubert #endif /* CONFIG_MBO */
44155b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
44165b9c547cSRui Paulo #define PARSE_TEST_PROBABILITY(_val)				\
44175b9c547cSRui Paulo 	} else if (os_strcmp(buf, #_val) == 0) {		\
44185b9c547cSRui Paulo 		char *end;					\
44195b9c547cSRui Paulo 								\
44205b9c547cSRui Paulo 		conf->_val = strtod(pos, &end);			\
44215b9c547cSRui Paulo 		if (*end || conf->_val < 0.0 ||			\
44225b9c547cSRui Paulo 		    conf->_val > 1.0) {				\
44235b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,			\
44245b9c547cSRui Paulo 				   "Line %d: Invalid value '%s'", \
44255b9c547cSRui Paulo 				   line, pos);			\
44265b9c547cSRui Paulo 			return 1;				\
44275b9c547cSRui Paulo 		}
44285b9c547cSRui Paulo 	PARSE_TEST_PROBABILITY(ignore_probe_probability)
44295b9c547cSRui Paulo 	PARSE_TEST_PROBABILITY(ignore_auth_probability)
44305b9c547cSRui Paulo 	PARSE_TEST_PROBABILITY(ignore_assoc_probability)
44315b9c547cSRui Paulo 	PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
44325b9c547cSRui Paulo 	PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
4433780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "ecsa_ie_only") == 0) {
4434780fb4a2SCy Schubert 		conf->ecsa_ie_only = atoi(pos);
44355b9c547cSRui Paulo 	} else if (os_strcmp(buf, "bss_load_test") == 0) {
44365b9c547cSRui Paulo 		WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
44375b9c547cSRui Paulo 		pos = os_strchr(pos, ':');
44385b9c547cSRui Paulo 		if (pos == NULL) {
44395b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
44405b9c547cSRui Paulo 				   line);
44415b9c547cSRui Paulo 			return 1;
44425b9c547cSRui Paulo 		}
44435b9c547cSRui Paulo 		pos++;
44445b9c547cSRui Paulo 		bss->bss_load_test[2] = atoi(pos);
44455b9c547cSRui Paulo 		pos = os_strchr(pos, ':');
44465b9c547cSRui Paulo 		if (pos == NULL) {
44475b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
44485b9c547cSRui Paulo 				   line);
44495b9c547cSRui Paulo 			return 1;
44505b9c547cSRui Paulo 		}
44515b9c547cSRui Paulo 		pos++;
44525b9c547cSRui Paulo 		WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
44535b9c547cSRui Paulo 		bss->bss_load_test_set = 1;
44545b9c547cSRui Paulo 	} else if (os_strcmp(buf, "radio_measurements") == 0) {
4455780fb4a2SCy Schubert 		/*
4456780fb4a2SCy Schubert 		 * DEPRECATED: This parameter will be removed in the future.
4457780fb4a2SCy Schubert 		 * Use rrm_neighbor_report instead.
4458780fb4a2SCy Schubert 		 */
4459780fb4a2SCy Schubert 		int val = atoi(pos);
4460780fb4a2SCy Schubert 
4461780fb4a2SCy Schubert 		if (val & BIT(0))
4462780fb4a2SCy Schubert 			bss->radio_measurements[0] |=
4463780fb4a2SCy Schubert 				WLAN_RRM_CAPS_NEIGHBOR_REPORT;
4464325151a3SRui Paulo 	} else if (os_strcmp(buf, "own_ie_override") == 0) {
4465325151a3SRui Paulo 		struct wpabuf *tmp;
4466325151a3SRui Paulo 		size_t len = os_strlen(pos) / 2;
4467325151a3SRui Paulo 
4468325151a3SRui Paulo 		tmp = wpabuf_alloc(len);
4469325151a3SRui Paulo 		if (!tmp)
4470325151a3SRui Paulo 			return 1;
4471325151a3SRui Paulo 
4472325151a3SRui Paulo 		if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
4473325151a3SRui Paulo 			wpabuf_free(tmp);
4474325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4475325151a3SRui Paulo 				   "Line %d: Invalid own_ie_override '%s'",
4476325151a3SRui Paulo 				   line, pos);
4477325151a3SRui Paulo 			return 1;
4478325151a3SRui Paulo 		}
4479325151a3SRui Paulo 
4480325151a3SRui Paulo 		wpabuf_free(bss->own_ie_override);
4481325151a3SRui Paulo 		bss->own_ie_override = tmp;
448285732ac8SCy Schubert 	} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
448385732ac8SCy Schubert 		bss->sae_reflection_attack = atoi(pos);
4484c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "sae_commit_status") == 0) {
4485c1d255d3SCy Schubert 		bss->sae_commit_status = atoi(pos);
4486c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "sae_pk_omit") == 0) {
4487c1d255d3SCy Schubert 		bss->sae_pk_omit = atoi(pos);
4488c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) {
4489c1d255d3SCy Schubert 		bss->sae_pk_password_check_skip = atoi(pos);
449085732ac8SCy Schubert 	} else if (os_strcmp(buf, "sae_commit_override") == 0) {
449185732ac8SCy Schubert 		wpabuf_free(bss->sae_commit_override);
449285732ac8SCy Schubert 		bss->sae_commit_override = wpabuf_parse_bin(pos);
4493c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "rsne_override_eapol") == 0) {
4494c1d255d3SCy Schubert 		wpabuf_free(bss->rsne_override_eapol);
4495c1d255d3SCy Schubert 		bss->rsne_override_eapol = wpabuf_parse_bin(pos);
4496c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
4497c1d255d3SCy Schubert 		wpabuf_free(bss->rsnxe_override_eapol);
4498c1d255d3SCy Schubert 		bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
4499c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "rsne_override_ft") == 0) {
4500c1d255d3SCy Schubert 		wpabuf_free(bss->rsne_override_ft);
4501c1d255d3SCy Schubert 		bss->rsne_override_ft = wpabuf_parse_bin(pos);
4502c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "rsnxe_override_ft") == 0) {
4503c1d255d3SCy Schubert 		wpabuf_free(bss->rsnxe_override_ft);
4504c1d255d3SCy Schubert 		bss->rsnxe_override_ft = wpabuf_parse_bin(pos);
4505c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
4506c1d255d3SCy Schubert 		wpabuf_free(bss->gtk_rsc_override);
4507c1d255d3SCy Schubert 		bss->gtk_rsc_override = wpabuf_parse_bin(pos);
4508c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
4509c1d255d3SCy Schubert 		wpabuf_free(bss->igtk_rsc_override);
4510c1d255d3SCy Schubert 		bss->igtk_rsc_override = wpabuf_parse_bin(pos);
4511c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) {
4512c1d255d3SCy Schubert 		bss->no_beacon_rsnxe = atoi(pos);
4513c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "skip_prune_assoc") == 0) {
4514c1d255d3SCy Schubert 		bss->skip_prune_assoc = atoi(pos);
4515c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "ft_rsnxe_used") == 0) {
4516c1d255d3SCy Schubert 		bss->ft_rsnxe_used = atoi(pos);
4517c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) {
4518c1d255d3SCy Schubert 		bss->oci_freq_override_eapol_m3 = atoi(pos);
4519c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) {
4520c1d255d3SCy Schubert 		bss->oci_freq_override_eapol_g1 = atoi(pos);
4521c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) {
4522c1d255d3SCy Schubert 		bss->oci_freq_override_saquery_req = atoi(pos);
4523c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) {
4524c1d255d3SCy Schubert 		bss->oci_freq_override_saquery_resp = atoi(pos);
4525c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) {
4526c1d255d3SCy Schubert 		bss->oci_freq_override_ft_assoc = atoi(pos);
4527c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) {
4528c1d255d3SCy Schubert 		bss->oci_freq_override_fils_assoc = atoi(pos);
4529c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
4530c1d255d3SCy Schubert 		bss->oci_freq_override_wnm_sleep = atoi(pos);
4531*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eap_skip_prot_success") == 0) {
4532*a90b9d01SCy Schubert 		bss->eap_skip_prot_success = atoi(pos);
4533*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "delay_eapol_tx") == 0) {
4534*a90b9d01SCy Schubert 		conf->delay_eapol_tx = atoi(pos);
4535*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eapol_m1_elements") == 0) {
4536*a90b9d01SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->eapol_m1_elements, pos))
4537*a90b9d01SCy Schubert 			return 1;
4538*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eapol_m3_elements") == 0) {
4539*a90b9d01SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->eapol_m3_elements, pos))
4540*a90b9d01SCy Schubert 			return 1;
4541*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
4542*a90b9d01SCy Schubert 		bss->eapol_m3_no_encrypt = atoi(pos);
4543*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
4544*a90b9d01SCy Schubert 		bss->test_assoc_comeback_type = atoi(pos);
4545*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "presp_elements") == 0) {
4546*a90b9d01SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->presp_elements, pos))
4547*a90b9d01SCy Schubert 			return 1;
45485b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
454985732ac8SCy Schubert #ifdef CONFIG_SAE
455085732ac8SCy Schubert 	} else if (os_strcmp(buf, "sae_password") == 0) {
455185732ac8SCy Schubert 		if (parse_sae_password(bss, pos) < 0) {
455285732ac8SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid sae_password",
455385732ac8SCy Schubert 				   line);
455485732ac8SCy Schubert 			return 1;
455585732ac8SCy Schubert 		}
4556*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "sae_password_file") == 0) {
4557*a90b9d01SCy Schubert 		if (parse_sae_password_file(bss, pos) < 0) {
4558*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
4559*a90b9d01SCy Schubert 				   "Line %d: Invalid sae_password in file",
4560*a90b9d01SCy Schubert 				   line);
4561*a90b9d01SCy Schubert 			return 1;
4562*a90b9d01SCy Schubert 		}
456385732ac8SCy Schubert #endif /* CONFIG_SAE */
4564f05cddf9SRui Paulo 	} else if (os_strcmp(buf, "vendor_elements") == 0) {
4565780fb4a2SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
4566f05cddf9SRui Paulo 			return 1;
4567780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "assocresp_elements") == 0) {
4568780fb4a2SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
4569f05cddf9SRui Paulo 			return 1;
4570c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0 ||
4571c1d255d3SCy Schubert 		   os_strcmp(buf, "anti_clogging_threshold") == 0) {
4572c1d255d3SCy Schubert 		bss->anti_clogging_threshold = atoi(pos);
457385732ac8SCy Schubert 	} else if (os_strcmp(buf, "sae_sync") == 0) {
457485732ac8SCy Schubert 		bss->sae_sync = atoi(pos);
45755b9c547cSRui Paulo 	} else if (os_strcmp(buf, "sae_groups") == 0) {
45765b9c547cSRui Paulo 		if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
45775b9c547cSRui Paulo 			wpa_printf(MSG_ERROR,
45785b9c547cSRui Paulo 				   "Line %d: Invalid sae_groups value '%s'",
45795b9c547cSRui Paulo 				   line, pos);
45805b9c547cSRui Paulo 			return 1;
45815b9c547cSRui Paulo 		}
458285732ac8SCy Schubert 	} else if (os_strcmp(buf, "sae_require_mfp") == 0) {
458385732ac8SCy Schubert 		bss->sae_require_mfp = atoi(pos);
4584c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "sae_confirm_immediate") == 0) {
4585c1d255d3SCy Schubert 		bss->sae_confirm_immediate = atoi(pos);
4586c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "sae_pwe") == 0) {
4587c1d255d3SCy Schubert 		bss->sae_pwe = atoi(pos);
45885b9c547cSRui Paulo 	} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
45895b9c547cSRui Paulo 		int val = atoi(pos);
45905b9c547cSRui Paulo 		if (val < 0 || val > 255) {
45915b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
45925b9c547cSRui Paulo 				   line, val);
45935b9c547cSRui Paulo 			return 1;
45945b9c547cSRui Paulo 		}
45955b9c547cSRui Paulo 		conf->local_pwr_constraint = val;
45965b9c547cSRui Paulo 	} else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
45975b9c547cSRui Paulo 		conf->spectrum_mgmt_required = atoi(pos);
45985b9c547cSRui Paulo 	} else if (os_strcmp(buf, "wowlan_triggers") == 0) {
45995b9c547cSRui Paulo 		os_free(bss->wowlan_triggers);
46005b9c547cSRui Paulo 		bss->wowlan_triggers = os_strdup(pos);
4601325151a3SRui Paulo #ifdef CONFIG_FST
4602325151a3SRui Paulo 	} else if (os_strcmp(buf, "fst_group_id") == 0) {
4603325151a3SRui Paulo 		size_t len = os_strlen(pos);
4604325151a3SRui Paulo 
4605325151a3SRui Paulo 		if (!len || len >= sizeof(conf->fst_cfg.group_id)) {
4606325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4607325151a3SRui Paulo 				   "Line %d: Invalid fst_group_id value '%s'",
4608325151a3SRui Paulo 				   line, pos);
4609325151a3SRui Paulo 			return 1;
4610325151a3SRui Paulo 		}
4611325151a3SRui Paulo 
4612325151a3SRui Paulo 		if (conf->fst_cfg.group_id[0]) {
4613325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4614325151a3SRui Paulo 				   "Line %d: Duplicate fst_group value '%s'",
4615325151a3SRui Paulo 				   line, pos);
4616325151a3SRui Paulo 			return 1;
4617325151a3SRui Paulo 		}
4618325151a3SRui Paulo 
4619325151a3SRui Paulo 		os_strlcpy(conf->fst_cfg.group_id, pos,
4620325151a3SRui Paulo 			   sizeof(conf->fst_cfg.group_id));
4621325151a3SRui Paulo 	} else if (os_strcmp(buf, "fst_priority") == 0) {
4622325151a3SRui Paulo 		char *endp;
4623325151a3SRui Paulo 		long int val;
4624325151a3SRui Paulo 
4625325151a3SRui Paulo 		if (!*pos) {
4626325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4627325151a3SRui Paulo 				   "Line %d: fst_priority value not supplied (expected 1..%u)",
4628325151a3SRui Paulo 				   line, FST_MAX_PRIO_VALUE);
4629325151a3SRui Paulo 			return -1;
4630325151a3SRui Paulo 		}
4631325151a3SRui Paulo 
4632325151a3SRui Paulo 		val = strtol(pos, &endp, 0);
4633325151a3SRui Paulo 		if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) {
4634325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4635325151a3SRui Paulo 				   "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)",
4636325151a3SRui Paulo 				   line, val, pos, FST_MAX_PRIO_VALUE);
4637325151a3SRui Paulo 			return 1;
4638325151a3SRui Paulo 		}
4639325151a3SRui Paulo 		conf->fst_cfg.priority = (u8) val;
4640325151a3SRui Paulo 	} else if (os_strcmp(buf, "fst_llt") == 0) {
4641325151a3SRui Paulo 		char *endp;
4642325151a3SRui Paulo 		long int val;
4643325151a3SRui Paulo 
4644325151a3SRui Paulo 		if (!*pos) {
4645325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4646325151a3SRui Paulo 				   "Line %d: fst_llt value not supplied (expected 1..%u)",
4647325151a3SRui Paulo 				   line, FST_MAX_LLT_MS);
4648325151a3SRui Paulo 			return -1;
4649325151a3SRui Paulo 		}
4650325151a3SRui Paulo 		val = strtol(pos, &endp, 0);
4651780fb4a2SCy Schubert 		if (*endp || val < 1 ||
4652780fb4a2SCy Schubert 		    (unsigned long int) val > FST_MAX_LLT_MS) {
4653325151a3SRui Paulo 			wpa_printf(MSG_ERROR,
4654325151a3SRui Paulo 				   "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
4655325151a3SRui Paulo 				   line, val, pos, FST_MAX_LLT_MS);
4656325151a3SRui Paulo 			return 1;
4657325151a3SRui Paulo 		}
4658325151a3SRui Paulo 		conf->fst_cfg.llt = (u32) val;
4659325151a3SRui Paulo #endif /* CONFIG_FST */
4660325151a3SRui Paulo 	} else if (os_strcmp(buf, "track_sta_max_num") == 0) {
4661325151a3SRui Paulo 		conf->track_sta_max_num = atoi(pos);
4662325151a3SRui Paulo 	} else if (os_strcmp(buf, "track_sta_max_age") == 0) {
4663325151a3SRui Paulo 		conf->track_sta_max_age = atoi(pos);
4664325151a3SRui Paulo 	} else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) {
4665325151a3SRui Paulo 		os_free(bss->no_probe_resp_if_seen_on);
4666325151a3SRui Paulo 		bss->no_probe_resp_if_seen_on = os_strdup(pos);
4667325151a3SRui Paulo 	} else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
4668325151a3SRui Paulo 		os_free(bss->no_auth_if_seen_on);
4669325151a3SRui Paulo 		bss->no_auth_if_seen_on = os_strdup(pos);
4670780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "lci") == 0) {
4671780fb4a2SCy Schubert 		wpabuf_free(conf->lci);
4672780fb4a2SCy Schubert 		conf->lci = wpabuf_parse_bin(pos);
467385732ac8SCy Schubert 		if (conf->lci && wpabuf_len(conf->lci) == 0) {
467485732ac8SCy Schubert 			wpabuf_free(conf->lci);
467585732ac8SCy Schubert 			conf->lci = NULL;
467685732ac8SCy Schubert 		}
4677780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "civic") == 0) {
4678780fb4a2SCy Schubert 		wpabuf_free(conf->civic);
4679780fb4a2SCy Schubert 		conf->civic = wpabuf_parse_bin(pos);
468085732ac8SCy Schubert 		if (conf->civic && wpabuf_len(conf->civic) == 0) {
468185732ac8SCy Schubert 			wpabuf_free(conf->civic);
468285732ac8SCy Schubert 			conf->civic = NULL;
468385732ac8SCy Schubert 		}
4684780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "rrm_neighbor_report") == 0) {
4685780fb4a2SCy Schubert 		if (atoi(pos))
4686780fb4a2SCy Schubert 			bss->radio_measurements[0] |=
4687780fb4a2SCy Schubert 				WLAN_RRM_CAPS_NEIGHBOR_REPORT;
468885732ac8SCy Schubert 	} else if (os_strcmp(buf, "rrm_beacon_report") == 0) {
468985732ac8SCy Schubert 		if (atoi(pos))
469085732ac8SCy Schubert 			bss->radio_measurements[0] |=
469185732ac8SCy Schubert 				WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
469285732ac8SCy Schubert 				WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
469385732ac8SCy Schubert 				WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
4694*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "rrm_link_measurement_report") == 0) {
4695*a90b9d01SCy Schubert 		if (atoi(pos))
4696*a90b9d01SCy Schubert 			bss->radio_measurements[0] |=
4697*a90b9d01SCy Schubert 				WLAN_RRM_CAPS_LINK_MEASUREMENT;
4698780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "gas_address3") == 0) {
4699780fb4a2SCy Schubert 		bss->gas_address3 = atoi(pos);
470085732ac8SCy Schubert 	} else if (os_strcmp(buf, "stationary_ap") == 0) {
470185732ac8SCy Schubert 		conf->stationary_ap = atoi(pos);
4702780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "ftm_responder") == 0) {
4703780fb4a2SCy Schubert 		bss->ftm_responder = atoi(pos);
4704780fb4a2SCy Schubert 	} else if (os_strcmp(buf, "ftm_initiator") == 0) {
4705780fb4a2SCy Schubert 		bss->ftm_initiator = atoi(pos);
470685732ac8SCy Schubert #ifdef CONFIG_FILS
470785732ac8SCy Schubert 	} else if (os_strcmp(buf, "fils_cache_id") == 0) {
470885732ac8SCy Schubert 		if (hexstr2bin(pos, bss->fils_cache_id, FILS_CACHE_ID_LEN)) {
470985732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
471085732ac8SCy Schubert 				   "Line %d: Invalid fils_cache_id '%s'",
471185732ac8SCy Schubert 				   line, pos);
471285732ac8SCy Schubert 			return 1;
471385732ac8SCy Schubert 		}
471485732ac8SCy Schubert 		bss->fils_cache_id_set = 1;
471585732ac8SCy Schubert 	} else if (os_strcmp(buf, "fils_realm") == 0) {
471685732ac8SCy Schubert 		if (parse_fils_realm(bss, pos) < 0)
471785732ac8SCy Schubert 			return 1;
471885732ac8SCy Schubert 	} else if (os_strcmp(buf, "fils_dh_group") == 0) {
471985732ac8SCy Schubert 		bss->fils_dh_group = atoi(pos);
472085732ac8SCy Schubert 	} else if (os_strcmp(buf, "dhcp_server") == 0) {
472185732ac8SCy Schubert 		if (hostapd_parse_ip_addr(pos, &bss->dhcp_server)) {
472285732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
472385732ac8SCy Schubert 				   "Line %d: invalid IP address '%s'",
472485732ac8SCy Schubert 				   line, pos);
472585732ac8SCy Schubert 			return 1;
472685732ac8SCy Schubert 		}
472785732ac8SCy Schubert 	} else if (os_strcmp(buf, "dhcp_rapid_commit_proxy") == 0) {
472885732ac8SCy Schubert 		bss->dhcp_rapid_commit_proxy = atoi(pos);
472985732ac8SCy Schubert 	} else if (os_strcmp(buf, "fils_hlp_wait_time") == 0) {
473085732ac8SCy Schubert 		bss->fils_hlp_wait_time = atoi(pos);
473185732ac8SCy Schubert 	} else if (os_strcmp(buf, "dhcp_server_port") == 0) {
473285732ac8SCy Schubert 		bss->dhcp_server_port = atoi(pos);
473385732ac8SCy Schubert 	} else if (os_strcmp(buf, "dhcp_relay_port") == 0) {
473485732ac8SCy Schubert 		bss->dhcp_relay_port = atoi(pos);
4735c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "fils_discovery_min_interval") == 0) {
4736c1d255d3SCy Schubert 		bss->fils_discovery_min_int = atoi(pos);
4737c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "fils_discovery_max_interval") == 0) {
4738c1d255d3SCy Schubert 		bss->fils_discovery_max_int = atoi(pos);
473985732ac8SCy Schubert #endif /* CONFIG_FILS */
474085732ac8SCy Schubert 	} else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
474185732ac8SCy Schubert 		bss->multicast_to_unicast = atoi(pos);
4742*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "bridge_multicast_to_unicast") == 0) {
4743*a90b9d01SCy Schubert 		bss->bridge_multicast_to_unicast = atoi(pos);
474485732ac8SCy Schubert 	} else if (os_strcmp(buf, "broadcast_deauth") == 0) {
474585732ac8SCy Schubert 		bss->broadcast_deauth = atoi(pos);
4746c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "notify_mgmt_frames") == 0) {
4747c1d255d3SCy Schubert 		bss->notify_mgmt_frames = atoi(pos);
474885732ac8SCy Schubert #ifdef CONFIG_DPP
4749c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "dpp_name") == 0) {
4750c1d255d3SCy Schubert 		os_free(bss->dpp_name);
4751c1d255d3SCy Schubert 		bss->dpp_name = os_strdup(pos);
4752c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "dpp_mud_url") == 0) {
4753c1d255d3SCy Schubert 		os_free(bss->dpp_mud_url);
4754c1d255d3SCy Schubert 		bss->dpp_mud_url = os_strdup(pos);
4755*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "dpp_extra_conf_req_name") == 0) {
4756*a90b9d01SCy Schubert 		os_free(bss->dpp_extra_conf_req_name);
4757*a90b9d01SCy Schubert 		bss->dpp_extra_conf_req_name = os_strdup(pos);
4758*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "dpp_extra_conf_req_value") == 0) {
4759*a90b9d01SCy Schubert 		os_free(bss->dpp_extra_conf_req_value);
4760*a90b9d01SCy Schubert 		bss->dpp_extra_conf_req_value = os_strdup(pos);
476185732ac8SCy Schubert 	} else if (os_strcmp(buf, "dpp_connector") == 0) {
476285732ac8SCy Schubert 		os_free(bss->dpp_connector);
476385732ac8SCy Schubert 		bss->dpp_connector = os_strdup(pos);
476485732ac8SCy Schubert 	} else if (os_strcmp(buf, "dpp_netaccesskey") == 0) {
476585732ac8SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->dpp_netaccesskey, pos))
476685732ac8SCy Schubert 			return 1;
476785732ac8SCy Schubert 	} else if (os_strcmp(buf, "dpp_netaccesskey_expiry") == 0) {
476885732ac8SCy Schubert 		bss->dpp_netaccesskey_expiry = strtol(pos, NULL, 0);
476985732ac8SCy Schubert 	} else if (os_strcmp(buf, "dpp_csign") == 0) {
477085732ac8SCy Schubert 		if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos))
477185732ac8SCy Schubert 			return 1;
4772206b73d0SCy Schubert #ifdef CONFIG_DPP2
4773206b73d0SCy Schubert 	} else if (os_strcmp(buf, "dpp_controller") == 0) {
4774206b73d0SCy Schubert 		if (hostapd_dpp_controller_parse(bss, pos))
4775206b73d0SCy Schubert 			return 1;
4776*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "dpp_relay_port") == 0) {
4777*a90b9d01SCy Schubert 		bss->dpp_relay_port = atoi(pos);
4778c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) {
4779c1d255d3SCy Schubert 		bss->dpp_configurator_connectivity = atoi(pos);
4780c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "dpp_pfs") == 0) {
4781c1d255d3SCy Schubert 		int val = atoi(pos);
4782c1d255d3SCy Schubert 
4783c1d255d3SCy Schubert 		if (val < 0 || val > 2) {
4784c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
4785c1d255d3SCy Schubert 				   "Line %d: Invalid dpp_pfs value '%s'",
4786c1d255d3SCy Schubert 				   line, pos);
4787c1d255d3SCy Schubert 			return -1;
4788c1d255d3SCy Schubert 		}
4789c1d255d3SCy Schubert 		bss->dpp_pfs = val;
4790206b73d0SCy Schubert #endif /* CONFIG_DPP2 */
479185732ac8SCy Schubert #endif /* CONFIG_DPP */
479285732ac8SCy Schubert #ifdef CONFIG_OWE
479385732ac8SCy Schubert 	} else if (os_strcmp(buf, "owe_transition_bssid") == 0) {
479485732ac8SCy Schubert 		if (hwaddr_aton(pos, bss->owe_transition_bssid)) {
479585732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
479685732ac8SCy Schubert 				   "Line %d: invalid owe_transition_bssid",
479785732ac8SCy Schubert 				   line);
479885732ac8SCy Schubert 			return 1;
479985732ac8SCy Schubert 		}
480085732ac8SCy Schubert 	} else if (os_strcmp(buf, "owe_transition_ssid") == 0) {
480185732ac8SCy Schubert 		size_t slen;
480285732ac8SCy Schubert 		char *str = wpa_config_parse_string(pos, &slen);
480385732ac8SCy Schubert 
480485732ac8SCy Schubert 		if (!str || slen < 1 || slen > SSID_MAX_LEN) {
480585732ac8SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
480685732ac8SCy Schubert 				   line, pos);
480785732ac8SCy Schubert 			os_free(str);
480885732ac8SCy Schubert 			return 1;
480985732ac8SCy Schubert 		}
481085732ac8SCy Schubert 		os_memcpy(bss->owe_transition_ssid, str, slen);
481185732ac8SCy Schubert 		bss->owe_transition_ssid_len = slen;
481285732ac8SCy Schubert 		os_free(str);
481385732ac8SCy Schubert 	} else if (os_strcmp(buf, "owe_transition_ifname") == 0) {
481485732ac8SCy Schubert 		os_strlcpy(bss->owe_transition_ifname, pos,
481585732ac8SCy Schubert 			   sizeof(bss->owe_transition_ifname));
481685732ac8SCy Schubert 	} else if (os_strcmp(buf, "owe_groups") == 0) {
481785732ac8SCy Schubert 		if (hostapd_parse_intlist(&bss->owe_groups, pos)) {
481885732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
481985732ac8SCy Schubert 				   "Line %d: Invalid owe_groups value '%s'",
482085732ac8SCy Schubert 				   line, pos);
482185732ac8SCy Schubert 			return 1;
482285732ac8SCy Schubert 		}
4823c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
4824c1d255d3SCy Schubert 		bss->owe_ptk_workaround = atoi(pos);
4825c1d255d3SCy Schubert #endif /* CONFIG_OWE */
482685732ac8SCy Schubert 	} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
482785732ac8SCy Schubert 		bss->coloc_intf_reporting = atoi(pos);
48284bc52338SCy Schubert 	} else if (os_strcmp(buf, "multi_ap") == 0) {
48294bc52338SCy Schubert 		int val = atoi(pos);
48304bc52338SCy Schubert 
48314bc52338SCy Schubert 		if (val < 0 || val > 3) {
48324bc52338SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'",
48334bc52338SCy Schubert 				   line, buf);
48344bc52338SCy Schubert 			return -1;
48354bc52338SCy Schubert 		}
48364bc52338SCy Schubert 
48374bc52338SCy Schubert 		bss->multi_ap = val;
4838*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
4839*a90b9d01SCy Schubert 		int val = atoi(pos);
4840*a90b9d01SCy Schubert 
4841*a90b9d01SCy Schubert 		if (val < MULTI_AP_PROFILE_1 || val > MULTI_AP_PROFILE_MAX) {
4842*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
4843*a90b9d01SCy Schubert 				   "Line %d: Invalid multi_ap_profile '%s'",
4844*a90b9d01SCy Schubert 				   line, buf);
4845*a90b9d01SCy Schubert 			return -1;
4846*a90b9d01SCy Schubert 		}
4847*a90b9d01SCy Schubert 		bss->multi_ap_profile = val;
4848*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "multi_ap_client_disallow") == 0) {
4849*a90b9d01SCy Schubert 		int val = atoi(pos);
4850*a90b9d01SCy Schubert 
4851*a90b9d01SCy Schubert 		if (val < 0 || val > 3) {
4852*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
4853*a90b9d01SCy Schubert 				   "Line %d: Invalid multi_ap_client_allow '%s'",
4854*a90b9d01SCy Schubert 				   line, buf);
4855*a90b9d01SCy Schubert 			return -1;
4856*a90b9d01SCy Schubert 		}
4857*a90b9d01SCy Schubert 		bss->multi_ap_client_disallow = val;
4858*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "multi_ap_vlanid") == 0) {
4859*a90b9d01SCy Schubert 		int val = atoi(pos);
4860*a90b9d01SCy Schubert 
4861*a90b9d01SCy Schubert 		if (val < 0 || val > MAX_VLAN_ID) {
4862*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
4863*a90b9d01SCy Schubert 				   "Line %d: Invalid multi_ap_vlan_id '%s'",
4864*a90b9d01SCy Schubert 				   line, buf);
4865*a90b9d01SCy Schubert 			return -1;
4866*a90b9d01SCy Schubert 		}
4867*a90b9d01SCy Schubert 		bss->multi_ap_vlanid = val;
48684bc52338SCy Schubert 	} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
48694bc52338SCy Schubert 		conf->rssi_reject_assoc_rssi = atoi(pos);
48704bc52338SCy Schubert 	} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
48714bc52338SCy Schubert 		conf->rssi_reject_assoc_timeout = atoi(pos);
4872c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) {
4873c1d255d3SCy Schubert 		conf->rssi_ignore_probe_request = atoi(pos);
48744bc52338SCy Schubert 	} else if (os_strcmp(buf, "pbss") == 0) {
48754bc52338SCy Schubert 		bss->pbss = atoi(pos);
4876c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "transition_disable") == 0) {
4877c1d255d3SCy Schubert 		bss->transition_disable = strtol(pos, NULL, 16);
4878206b73d0SCy Schubert #ifdef CONFIG_AIRTIME_POLICY
4879206b73d0SCy Schubert 	} else if (os_strcmp(buf, "airtime_mode") == 0) {
4880206b73d0SCy Schubert 		int val = atoi(pos);
4881206b73d0SCy Schubert 
4882206b73d0SCy Schubert 		if (val < 0 || val > AIRTIME_MODE_MAX) {
4883206b73d0SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Unknown airtime_mode",
4884206b73d0SCy Schubert 				   line);
4885206b73d0SCy Schubert 			return 1;
4886206b73d0SCy Schubert 		}
4887206b73d0SCy Schubert 		conf->airtime_mode = val;
4888206b73d0SCy Schubert 	} else if (os_strcmp(buf, "airtime_update_interval") == 0) {
4889206b73d0SCy Schubert 		conf->airtime_update_interval = atoi(pos);
4890206b73d0SCy Schubert 	} else if (os_strcmp(buf, "airtime_bss_weight") == 0) {
4891206b73d0SCy Schubert 		bss->airtime_weight = atoi(pos);
4892206b73d0SCy Schubert 	} else if (os_strcmp(buf, "airtime_bss_limit") == 0) {
4893206b73d0SCy Schubert 		int val = atoi(pos);
4894206b73d0SCy Schubert 
4895206b73d0SCy Schubert 		if (val < 0 || val > 1) {
4896206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4897206b73d0SCy Schubert 				   "Line %d: Invalid airtime_bss_limit (must be 0 or 1)",
4898206b73d0SCy Schubert 				   line);
4899206b73d0SCy Schubert 			return 1;
4900206b73d0SCy Schubert 		}
4901206b73d0SCy Schubert 		bss->airtime_limit = val;
4902206b73d0SCy Schubert 	} else if (os_strcmp(buf, "airtime_sta_weight") == 0) {
4903206b73d0SCy Schubert 		if (add_airtime_weight(bss, pos) < 0) {
4904206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4905206b73d0SCy Schubert 				   "Line %d: Invalid airtime weight '%s'",
4906206b73d0SCy Schubert 				   line, pos);
4907206b73d0SCy Schubert 			return 1;
4908206b73d0SCy Schubert 		}
4909206b73d0SCy Schubert #endif /* CONFIG_AIRTIME_POLICY */
4910206b73d0SCy Schubert #ifdef CONFIG_MACSEC
4911206b73d0SCy Schubert 	} else if (os_strcmp(buf, "macsec_policy") == 0) {
4912206b73d0SCy Schubert 		int macsec_policy = atoi(pos);
4913206b73d0SCy Schubert 
4914206b73d0SCy Schubert 		if (macsec_policy < 0 || macsec_policy > 1) {
4915206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4916206b73d0SCy Schubert 				   "Line %d: invalid macsec_policy (%d): '%s'.",
4917206b73d0SCy Schubert 				   line, macsec_policy, pos);
4918206b73d0SCy Schubert 			return 1;
4919206b73d0SCy Schubert 		}
4920206b73d0SCy Schubert 		bss->macsec_policy = macsec_policy;
4921206b73d0SCy Schubert 	} else if (os_strcmp(buf, "macsec_integ_only") == 0) {
4922206b73d0SCy Schubert 		int macsec_integ_only = atoi(pos);
4923206b73d0SCy Schubert 
4924206b73d0SCy Schubert 		if (macsec_integ_only < 0 || macsec_integ_only > 1) {
4925206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4926206b73d0SCy Schubert 				   "Line %d: invalid macsec_integ_only (%d): '%s'.",
4927206b73d0SCy Schubert 				   line, macsec_integ_only, pos);
4928206b73d0SCy Schubert 			return 1;
4929206b73d0SCy Schubert 		}
4930206b73d0SCy Schubert 		bss->macsec_integ_only = macsec_integ_only;
4931206b73d0SCy Schubert 	} else if (os_strcmp(buf, "macsec_replay_protect") == 0) {
4932206b73d0SCy Schubert 		int macsec_replay_protect = atoi(pos);
4933206b73d0SCy Schubert 
4934206b73d0SCy Schubert 		if (macsec_replay_protect < 0 || macsec_replay_protect > 1) {
4935206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4936206b73d0SCy Schubert 				   "Line %d: invalid macsec_replay_protect (%d): '%s'.",
4937206b73d0SCy Schubert 				   line, macsec_replay_protect, pos);
4938206b73d0SCy Schubert 			return 1;
4939206b73d0SCy Schubert 		}
4940206b73d0SCy Schubert 		bss->macsec_replay_protect = macsec_replay_protect;
4941206b73d0SCy Schubert 	} else if (os_strcmp(buf, "macsec_replay_window") == 0) {
4942206b73d0SCy Schubert 		bss->macsec_replay_window = atoi(pos);
4943*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "macsec_offload") == 0) {
4944*a90b9d01SCy Schubert 		int macsec_offload = atoi(pos);
4945*a90b9d01SCy Schubert 
4946*a90b9d01SCy Schubert 		if (macsec_offload < 0 || macsec_offload > 2) {
4947*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
4948*a90b9d01SCy Schubert 				   "Line %d: invalid macsec_offload (%d): '%s'.",
4949*a90b9d01SCy Schubert 				   line, macsec_offload, pos);
4950*a90b9d01SCy Schubert 			return 1;
4951*a90b9d01SCy Schubert 		}
4952*a90b9d01SCy Schubert 		bss->macsec_offload = macsec_offload;
4953206b73d0SCy Schubert 	} else if (os_strcmp(buf, "macsec_port") == 0) {
4954206b73d0SCy Schubert 		int macsec_port = atoi(pos);
4955206b73d0SCy Schubert 
4956206b73d0SCy Schubert 		if (macsec_port < 1 || macsec_port > 65534) {
4957206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4958206b73d0SCy Schubert 				   "Line %d: invalid macsec_port (%d): '%s'.",
4959206b73d0SCy Schubert 				   line, macsec_port, pos);
4960206b73d0SCy Schubert 			return 1;
4961206b73d0SCy Schubert 		}
4962206b73d0SCy Schubert 		bss->macsec_port = macsec_port;
4963206b73d0SCy Schubert 	} else if (os_strcmp(buf, "mka_priority") == 0) {
4964206b73d0SCy Schubert 		int mka_priority = atoi(pos);
4965206b73d0SCy Schubert 
4966206b73d0SCy Schubert 		if (mka_priority < 0 || mka_priority > 255) {
4967206b73d0SCy Schubert 			wpa_printf(MSG_ERROR,
4968206b73d0SCy Schubert 				   "Line %d: invalid mka_priority (%d): '%s'.",
4969206b73d0SCy Schubert 				   line, mka_priority, pos);
4970206b73d0SCy Schubert 			return 1;
4971206b73d0SCy Schubert 		}
4972206b73d0SCy Schubert 		bss->mka_priority = mka_priority;
4973*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "macsec_csindex") == 0) {
4974*a90b9d01SCy Schubert 		int macsec_csindex = atoi(pos);
4975*a90b9d01SCy Schubert 
4976*a90b9d01SCy Schubert 		if (macsec_csindex < 0 || macsec_csindex > 1) {
4977*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
4978*a90b9d01SCy Schubert 				   "Line %d: invalid macsec_csindex (%d): '%s'.",
4979*a90b9d01SCy Schubert 				   line, macsec_csindex, pos);
4980*a90b9d01SCy Schubert 			return 1;
4981*a90b9d01SCy Schubert 		}
4982*a90b9d01SCy Schubert 		bss->macsec_csindex = macsec_csindex;
4983206b73d0SCy Schubert 	} else if (os_strcmp(buf, "mka_cak") == 0) {
4984206b73d0SCy Schubert 		size_t len = os_strlen(pos);
4985206b73d0SCy Schubert 
4986206b73d0SCy Schubert 		if (len > 2 * MACSEC_CAK_MAX_LEN ||
4987206b73d0SCy Schubert 		    (len != 2 * 16 && len != 2 * 32) ||
4988206b73d0SCy Schubert 		    hexstr2bin(pos, bss->mka_cak, len / 2)) {
4989206b73d0SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
4990206b73d0SCy Schubert 				   line, pos);
4991206b73d0SCy Schubert 			return 1;
4992206b73d0SCy Schubert 		}
4993206b73d0SCy Schubert 		bss->mka_cak_len = len / 2;
4994206b73d0SCy Schubert 		bss->mka_psk_set |= MKA_PSK_SET_CAK;
4995206b73d0SCy Schubert 	} else if (os_strcmp(buf, "mka_ckn") == 0) {
4996206b73d0SCy Schubert 		size_t len = os_strlen(pos);
4997206b73d0SCy Schubert 
4998206b73d0SCy Schubert 		if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
4999206b73d0SCy Schubert 		    len < 2 || /* too short */
5000206b73d0SCy Schubert 		    len % 2 != 0 /* not an integral number of bytes */) {
5001206b73d0SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
5002206b73d0SCy Schubert 				   line, pos);
5003206b73d0SCy Schubert 			return 1;
5004206b73d0SCy Schubert 		}
5005206b73d0SCy Schubert 		bss->mka_ckn_len = len / 2;
5006206b73d0SCy Schubert 		if (hexstr2bin(pos, bss->mka_ckn, bss->mka_ckn_len)) {
5007206b73d0SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
5008206b73d0SCy Schubert 				   line, pos);
5009206b73d0SCy Schubert 			return -1;
5010206b73d0SCy Schubert 		}
5011206b73d0SCy Schubert 		bss->mka_psk_set |= MKA_PSK_SET_CKN;
5012206b73d0SCy Schubert #endif /* CONFIG_MACSEC */
5013c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "disable_11n") == 0) {
5014c1d255d3SCy Schubert 		bss->disable_11n = !!atoi(pos);
5015c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "disable_11ac") == 0) {
5016c1d255d3SCy Schubert 		bss->disable_11ac = !!atoi(pos);
5017c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "disable_11ax") == 0) {
5018c1d255d3SCy Schubert 		bss->disable_11ax = !!atoi(pos);
5019*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "disable_11be") == 0) {
5020*a90b9d01SCy Schubert 		bss->disable_11be = !!atoi(pos);
5021c1d255d3SCy Schubert #ifdef CONFIG_PASN
5022c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
5023c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "force_kdk_derivation") == 0) {
5024c1d255d3SCy Schubert 		bss->force_kdk_derivation = atoi(pos);
5025c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) {
5026c1d255d3SCy Schubert 		bss->pasn_corrupt_mic = atoi(pos);
5027c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
5028c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "pasn_groups") == 0) {
5029c1d255d3SCy Schubert 		if (hostapd_parse_intlist(&bss->pasn_groups, pos)) {
5030c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
5031c1d255d3SCy Schubert 				   "Line %d: Invalid pasn_groups value '%s'",
5032c1d255d3SCy Schubert 				   line, pos);
5033c1d255d3SCy Schubert 			return 1;
5034c1d255d3SCy Schubert 		}
5035c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
5036c1d255d3SCy Schubert 		bss->pasn_comeback_after = atoi(pos);
5037*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "pasn_noauth") == 0) {
5038*a90b9d01SCy Schubert 		bss->pasn_noauth = atoi(pos);
5039c1d255d3SCy Schubert #endif /* CONFIG_PASN */
5040c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
5041c1d255d3SCy Schubert 		if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
5042c1d255d3SCy Schubert 				   line, "ext_capa_mask", pos))
5043c1d255d3SCy Schubert 			return 1;
5044c1d255d3SCy Schubert 	} else if (os_strcmp(buf, "ext_capa") == 0) {
5045c1d255d3SCy Schubert 		if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
5046c1d255d3SCy Schubert 				   line, "ext_capa", pos))
5047c1d255d3SCy Schubert 			return 1;
50484b72b91aSCy Schubert 	} else if (os_strcmp(buf, "rnr") == 0) {
50494b72b91aSCy Schubert 		bss->rnr = atoi(pos);
5050*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "ssid_protection") == 0) {
5051*a90b9d01SCy Schubert 		int val = atoi(pos);
5052*a90b9d01SCy Schubert 
5053*a90b9d01SCy Schubert 		if (val < 0 || val > 1)
5054*a90b9d01SCy Schubert 			return 1;
5055*a90b9d01SCy Schubert 		bss->ssid_protection = val;
5056*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE
5057*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "ieee80211be") == 0) {
5058*a90b9d01SCy Schubert 		conf->ieee80211be = atoi(pos);
5059*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_oper_chwidth") == 0) {
5060*a90b9d01SCy Schubert 		conf->eht_oper_chwidth = atoi(pos);
5061*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) {
5062*a90b9d01SCy Schubert 		conf->eht_oper_centr_freq_seg0_idx = atoi(pos);
5063*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_su_beamformer") == 0) {
5064*a90b9d01SCy Schubert 		conf->eht_phy_capab.su_beamformer = atoi(pos);
5065*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_su_beamformee") == 0) {
5066*a90b9d01SCy Schubert 		conf->eht_phy_capab.su_beamformee = atoi(pos);
5067*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_mu_beamformer") == 0) {
5068*a90b9d01SCy Schubert 		conf->eht_phy_capab.mu_beamformer = atoi(pos);
5069*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_default_pe_duration") == 0) {
5070*a90b9d01SCy Schubert 		conf->eht_default_pe_duration = atoi(pos);
5071*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "punct_bitmap") == 0) {
5072*a90b9d01SCy Schubert 		if (get_u16(pos, line, &conf->punct_bitmap))
5073*a90b9d01SCy Schubert 			return 1;
5074*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "punct_acs_threshold") == 0) {
5075*a90b9d01SCy Schubert 		int val = atoi(pos);
5076*a90b9d01SCy Schubert 
5077*a90b9d01SCy Schubert 		if (val < 0 || val > 100) {
5078*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR,
5079*a90b9d01SCy Schubert 				   "Line %d: punct_acs_threshold must be between 0 and 100",
5080*a90b9d01SCy Schubert 				   line);
5081*a90b9d01SCy Schubert 			return 1;
5082*a90b9d01SCy Schubert 		}
5083*a90b9d01SCy Schubert 		conf->punct_acs_threshold = val;
5084*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "mld_ap") == 0) {
5085*a90b9d01SCy Schubert 		bss->mld_ap = !!atoi(pos);
5086*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "mld_addr") == 0) {
5087*a90b9d01SCy Schubert 		if (hwaddr_aton(pos, bss->mld_addr)) {
5088*a90b9d01SCy Schubert 			wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr",
5089*a90b9d01SCy Schubert 				   line);
5090*a90b9d01SCy Schubert 			return 1;
5091*a90b9d01SCy Schubert 		}
5092*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_bw320_offset") == 0) {
5093*a90b9d01SCy Schubert 		conf->eht_bw320_offset = atoi(pos);
5094*a90b9d01SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
5095*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "eht_oper_puncturing_override") == 0) {
5096*a90b9d01SCy Schubert 		if (get_u16(pos, line, &bss->eht_oper_puncturing_override))
5097*a90b9d01SCy Schubert 			return 1;
5098*a90b9d01SCy Schubert 	} else if (os_strcmp(buf, "mld_indicate_disabled") == 0) {
5099*a90b9d01SCy Schubert 		bss->mld_indicate_disabled = atoi(pos);
5100*a90b9d01SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
5101*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */
5102e28a4053SRui Paulo 	} else {
51035b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
51045b9c547cSRui Paulo 			   "Line %d: unknown configuration item '%s'",
51055b9c547cSRui Paulo 			   line, buf);
51065b9c547cSRui Paulo 		return 1;
5107e28a4053SRui Paulo 	}
5108e28a4053SRui Paulo 
51095b9c547cSRui Paulo 	return 0;
5110f05cddf9SRui Paulo }
5111f05cddf9SRui Paulo 
5112f05cddf9SRui Paulo 
5113f05cddf9SRui Paulo /**
5114f05cddf9SRui Paulo  * hostapd_config_read - Read and parse a configuration file
5115f05cddf9SRui Paulo  * @fname: Configuration file name (including path, if needed)
5116f05cddf9SRui Paulo  * Returns: Allocated configuration data structure
5117f05cddf9SRui Paulo  */
hostapd_config_read(const char * fname)5118f05cddf9SRui Paulo struct hostapd_config * hostapd_config_read(const char *fname)
5119f05cddf9SRui Paulo {
5120f05cddf9SRui Paulo 	struct hostapd_config *conf;
5121f05cddf9SRui Paulo 	FILE *f;
5122780fb4a2SCy Schubert 	char buf[4096], *pos;
5123f05cddf9SRui Paulo 	int line = 0;
5124f05cddf9SRui Paulo 	int errors = 0;
5125f05cddf9SRui Paulo 	size_t i;
5126f05cddf9SRui Paulo 
5127f05cddf9SRui Paulo 	f = fopen(fname, "r");
5128f05cddf9SRui Paulo 	if (f == NULL) {
5129f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
5130f05cddf9SRui Paulo 			   "for reading.", fname);
5131f05cddf9SRui Paulo 		return NULL;
5132f05cddf9SRui Paulo 	}
5133f05cddf9SRui Paulo 
5134f05cddf9SRui Paulo 	conf = hostapd_config_defaults();
5135f05cddf9SRui Paulo 	if (conf == NULL) {
5136f05cddf9SRui Paulo 		fclose(f);
5137f05cddf9SRui Paulo 		return NULL;
5138f05cddf9SRui Paulo 	}
5139f05cddf9SRui Paulo 
5140f05cddf9SRui Paulo 	/* set default driver based on configuration */
5141f05cddf9SRui Paulo 	conf->driver = wpa_drivers[0];
5142f05cddf9SRui Paulo 	if (conf->driver == NULL) {
5143f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
5144f05cddf9SRui Paulo 		hostapd_config_free(conf);
5145f05cddf9SRui Paulo 		fclose(f);
5146f05cddf9SRui Paulo 		return NULL;
5147f05cddf9SRui Paulo 	}
5148f05cddf9SRui Paulo 
51495b9c547cSRui Paulo 	conf->last_bss = conf->bss[0];
5150f05cddf9SRui Paulo 
5151f05cddf9SRui Paulo 	while (fgets(buf, sizeof(buf), f)) {
51525b9c547cSRui Paulo 		struct hostapd_bss_config *bss;
51535b9c547cSRui Paulo 
5154f05cddf9SRui Paulo 		bss = conf->last_bss;
5155f05cddf9SRui Paulo 		line++;
5156f05cddf9SRui Paulo 
5157f05cddf9SRui Paulo 		if (buf[0] == '#')
5158f05cddf9SRui Paulo 			continue;
5159f05cddf9SRui Paulo 		pos = buf;
5160f05cddf9SRui Paulo 		while (*pos != '\0') {
5161f05cddf9SRui Paulo 			if (*pos == '\n') {
5162f05cddf9SRui Paulo 				*pos = '\0';
5163f05cddf9SRui Paulo 				break;
5164f05cddf9SRui Paulo 			}
5165f05cddf9SRui Paulo 			pos++;
5166f05cddf9SRui Paulo 		}
5167f05cddf9SRui Paulo 		if (buf[0] == '\0')
5168f05cddf9SRui Paulo 			continue;
5169f05cddf9SRui Paulo 
5170f05cddf9SRui Paulo 		pos = os_strchr(buf, '=');
5171f05cddf9SRui Paulo 		if (pos == NULL) {
5172f05cddf9SRui Paulo 			wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
5173f05cddf9SRui Paulo 				   line, buf);
5174f05cddf9SRui Paulo 			errors++;
5175f05cddf9SRui Paulo 			continue;
5176f05cddf9SRui Paulo 		}
5177f05cddf9SRui Paulo 		*pos = '\0';
5178f05cddf9SRui Paulo 		pos++;
5179f05cddf9SRui Paulo 		errors += hostapd_config_fill(conf, bss, buf, pos, line);
5180f05cddf9SRui Paulo 	}
5181f05cddf9SRui Paulo 
5182f05cddf9SRui Paulo 	fclose(f);
5183f05cddf9SRui Paulo 
5184f05cddf9SRui Paulo 	for (i = 0; i < conf->num_bss; i++)
51855b9c547cSRui Paulo 		hostapd_set_security_params(conf->bss[i], 1);
5186e28a4053SRui Paulo 
51875b9c547cSRui Paulo 	if (hostapd_config_check(conf, 1))
5188e28a4053SRui Paulo 		errors++;
5189e28a4053SRui Paulo 
5190f05cddf9SRui Paulo #ifndef WPA_IGNORE_CONFIG_ERRORS
5191e28a4053SRui Paulo 	if (errors) {
5192e28a4053SRui Paulo 		wpa_printf(MSG_ERROR, "%d errors found in configuration file "
5193e28a4053SRui Paulo 			   "'%s'", errors, fname);
5194e28a4053SRui Paulo 		hostapd_config_free(conf);
5195e28a4053SRui Paulo 		conf = NULL;
5196e28a4053SRui Paulo 	}
5197f05cddf9SRui Paulo #endif /* WPA_IGNORE_CONFIG_ERRORS */
5198e28a4053SRui Paulo 
5199e28a4053SRui Paulo 	return conf;
5200e28a4053SRui Paulo }
5201f05cddf9SRui Paulo 
5202f05cddf9SRui Paulo 
hostapd_set_iface(struct hostapd_config * conf,struct hostapd_bss_config * bss,const char * field,char * value)5203f05cddf9SRui Paulo int hostapd_set_iface(struct hostapd_config *conf,
5204325151a3SRui Paulo 		      struct hostapd_bss_config *bss, const char *field,
5205325151a3SRui Paulo 		      char *value)
5206f05cddf9SRui Paulo {
5207f05cddf9SRui Paulo 	int errors;
5208f05cddf9SRui Paulo 	size_t i;
5209f05cddf9SRui Paulo 
5210f05cddf9SRui Paulo 	errors = hostapd_config_fill(conf, bss, field, value, 0);
5211f05cddf9SRui Paulo 	if (errors) {
5212f05cddf9SRui Paulo 		wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
5213f05cddf9SRui Paulo 			   "to value '%s'", field, value);
5214f05cddf9SRui Paulo 		return -1;
5215f05cddf9SRui Paulo 	}
5216f05cddf9SRui Paulo 
5217f05cddf9SRui Paulo 	for (i = 0; i < conf->num_bss; i++)
52185b9c547cSRui Paulo 		hostapd_set_security_params(conf->bss[i], 0);
5219f05cddf9SRui Paulo 
52205b9c547cSRui Paulo 	if (hostapd_config_check(conf, 0)) {
5221f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Configuration check failed");
5222f05cddf9SRui Paulo 		return -1;
5223f05cddf9SRui Paulo 	}
5224f05cddf9SRui Paulo 
5225f05cddf9SRui Paulo 	return 0;
5226f05cddf9SRui Paulo }
5227