• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hostapd / Configuration file parser
3  * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 #ifndef CONFIG_NATIVE_WINDOWS
11 #include <grp.h>
12 #endif /* CONFIG_NATIVE_WINDOWS */
13 
14 #include "utils/common.h"
15 #include "utils/uuid.h"
16 #include "utils/crc32.h"
17 #include "common/ieee802_11_defs.h"
18 #include "common/sae.h"
19 #include "crypto/sha256.h"
20 #include "crypto/tls.h"
21 #include "drivers/driver.h"
22 #include "eap_server/eap.h"
23 #include "radius/radius_client.h"
24 #include "ap/wpa_auth.h"
25 #include "ap/ap_config.h"
26 #include "config_file.h"
27 
28 #ifdef CONFIG_OPEN_HARMONY_PATCH
29 #define HT40_OFFSET_DOWN 5
30 #define HT40_OFFSET_UP 13
31 #define PASS_MIN_LENGTH 8
32 #define PASS_MAX_LENGTH 65
33 static char g_hostapdPassphrase[PASS_MAX_LENGTH];
34 #endif
35 
36 #ifndef CONFIG_NO_VLAN
hostapd_config_read_vlan_file(struct hostapd_bss_config * bss,const char * fname)37 static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
38 					 const char *fname)
39 {
40 	FILE *f;
41 	char buf[128], *pos, *pos2, *pos3;
42 	int line = 0, vlan_id;
43 	struct hostapd_vlan *vlan;
44 
45 	f = fopen(fname, "r");
46 	if (!f) {
47 		wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname);
48 		return -1;
49 	}
50 
51 	while (fgets(buf, sizeof(buf), f)) {
52 		line++;
53 
54 		if (buf[0] == '#')
55 			continue;
56 		pos = buf;
57 		while (*pos != '\0') {
58 			if (*pos == '\n') {
59 				*pos = '\0';
60 				break;
61 			}
62 			pos++;
63 		}
64 		if (buf[0] == '\0')
65 			continue;
66 
67 		if (buf[0] == '*') {
68 			vlan_id = VLAN_ID_WILDCARD;
69 			pos = buf + 1;
70 		} else {
71 			vlan_id = strtol(buf, &pos, 10);
72 			if (buf == pos || vlan_id < 1 ||
73 			    vlan_id > MAX_VLAN_ID) {
74 				wpa_printf(MSG_ERROR, "Invalid VLAN ID at "
75 					   "line %d in '%s'", line, fname);
76 				fclose(f);
77 				return -1;
78 			}
79 		}
80 
81 		while (*pos == ' ' || *pos == '\t')
82 			pos++;
83 		pos2 = pos;
84 		while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
85 			pos2++;
86 
87 		if (*pos2 != '\0')
88 			*(pos2++) = '\0';
89 
90 		if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
91 			wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
92 				   "in '%s'", line, fname);
93 			fclose(f);
94 			return -1;
95 		}
96 
97 		while (*pos2 == ' ' || *pos2 == '\t')
98 			pos2++;
99 		pos3 = pos2;
100 		while (*pos3 != ' ' && *pos3 != '\t' && *pos3 != '\0')
101 			pos3++;
102 		*pos3 = '\0';
103 
104 		vlan = os_zalloc(sizeof(*vlan));
105 		if (vlan == NULL) {
106 			wpa_printf(MSG_ERROR, "Out of memory while reading "
107 				   "VLAN interfaces from '%s'", fname);
108 			fclose(f);
109 			return -1;
110 		}
111 
112 		vlan->vlan_id = vlan_id;
113 		vlan->vlan_desc.untagged = vlan_id;
114 		vlan->vlan_desc.notempty = !!vlan_id;
115 		os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
116 		os_strlcpy(vlan->bridge, pos2, sizeof(vlan->bridge));
117 		vlan->next = bss->vlan;
118 		bss->vlan = vlan;
119 	}
120 
121 	fclose(f);
122 
123 	return 0;
124 }
125 #endif /* CONFIG_NO_VLAN */
126 
127 
hostapd_config_read_maclist(const char * fname,struct mac_acl_entry ** acl,int * num)128 static int hostapd_config_read_maclist(const char *fname,
129 				       struct mac_acl_entry **acl, int *num)
130 {
131 	FILE *f;
132 	char buf[128], *pos;
133 	int line = 0;
134 	u8 addr[ETH_ALEN];
135 	int vlan_id;
136 
137 	f = fopen(fname, "r");
138 	if (!f) {
139 		wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname);
140 		return -1;
141 	}
142 
143 	while (fgets(buf, sizeof(buf), f)) {
144 		int rem = 0;
145 
146 		line++;
147 
148 		if (buf[0] == '#')
149 			continue;
150 		pos = buf;
151 		while (*pos != '\0') {
152 			if (*pos == '\n') {
153 				*pos = '\0';
154 				break;
155 			}
156 			pos++;
157 		}
158 		if (buf[0] == '\0')
159 			continue;
160 		pos = buf;
161 		if (buf[0] == '-') {
162 			rem = 1;
163 			pos++;
164 		}
165 
166 		if (hwaddr_aton(pos, addr)) {
167 			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
168 				   "line %d in '%s'", anonymize_common(pos), line, fname);
169 			fclose(f);
170 			return -1;
171 		}
172 
173 		if (rem) {
174 			hostapd_remove_acl_mac(acl, num, addr);
175 			continue;
176 		}
177 		vlan_id = 0;
178 		pos = buf;
179 		while (*pos != '\0' && *pos != ' ' && *pos != '\t')
180 			pos++;
181 		while (*pos == ' ' || *pos == '\t')
182 			pos++;
183 		if (*pos != '\0')
184 			vlan_id = atoi(pos);
185 
186 		if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) {
187 			fclose(f);
188 			return -1;
189 		}
190 	}
191 
192 	fclose(f);
193 
194 	if (*acl)
195 		qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
196 
197 	return 0;
198 }
199 
200 
201 #ifdef EAP_SERVER
202 
hostapd_config_eap_user_salted(struct hostapd_eap_user * user,const char * hash,size_t len,char ** pos,int line,const char * fname)203 static int hostapd_config_eap_user_salted(struct hostapd_eap_user *user,
204 					  const char *hash, size_t len,
205 					  char **pos, int line,
206 					  const char *fname)
207 {
208 	char *pos2 = *pos;
209 
210 	while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t' && *pos2 != '#')
211 		pos2++;
212 
213 	if (pos2 - *pos < (int) (2 * (len + 1))) { /* at least 1 byte of salt */
214 		wpa_printf(MSG_ERROR,
215 			   "Invalid salted %s hash on line %d in '%s'",
216 			   hash, line, fname);
217 		return -1;
218 	}
219 
220 	user->password = os_malloc(len);
221 	if (!user->password) {
222 		wpa_printf(MSG_ERROR,
223 			   "Failed to allocate memory for salted %s hash",
224 			   hash);
225 		return -1;
226 	}
227 
228 	if (hexstr2bin(*pos, user->password, len) < 0) {
229 		wpa_printf(MSG_ERROR,
230 			   "Invalid salted password on line %d in '%s'",
231 			   line, fname);
232 		return -1;
233 	}
234 	user->password_len = len;
235 	*pos += 2 * len;
236 
237 	user->salt_len = (pos2 - *pos) / 2;
238 	user->salt = os_malloc(user->salt_len);
239 	if (!user->salt) {
240 		wpa_printf(MSG_ERROR,
241 			   "Failed to allocate memory for salted %s hash",
242 			   hash);
243 		return -1;
244 	}
245 
246 	if (hexstr2bin(*pos, user->salt, user->salt_len) < 0) {
247 		wpa_printf(MSG_ERROR,
248 			   "Invalid salt for password on line %d in '%s'",
249 			   line, fname);
250 		return -1;
251 	}
252 
253 	*pos = pos2;
254 	return 0;
255 }
256 
257 
hostapd_config_read_eap_user(const char * fname,struct hostapd_bss_config * conf)258 static int hostapd_config_read_eap_user(const char *fname,
259 					struct hostapd_bss_config *conf)
260 {
261 	FILE *f;
262 	char buf[512], *pos, *start, *pos2;
263 	int line = 0, ret = 0, num_methods;
264 	struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
265 
266 	if (os_strncmp(fname, "sqlite:", 7) == 0) {
267 #ifdef CONFIG_SQLITE
268 		os_free(conf->eap_user_sqlite);
269 		conf->eap_user_sqlite = os_strdup(fname + 7);
270 		return 0;
271 #else /* CONFIG_SQLITE */
272 		wpa_printf(MSG_ERROR,
273 			   "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
274 		return -1;
275 #endif /* CONFIG_SQLITE */
276 	}
277 
278 	f = fopen(fname, "r");
279 	if (!f) {
280 		wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname);
281 		return -1;
282 	}
283 
284 	/* Lines: "user" METHOD,METHOD2 "password" (password optional) */
285 	while (fgets(buf, sizeof(buf), f)) {
286 		line++;
287 
288 		if (buf[0] == '#')
289 			continue;
290 		pos = buf;
291 		while (*pos != '\0') {
292 			if (*pos == '\n') {
293 				*pos = '\0';
294 				break;
295 			}
296 			pos++;
297 		}
298 		if (buf[0] == '\0')
299 			continue;
300 
301 #ifndef CONFIG_NO_RADIUS
302 		if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
303 			struct hostapd_radius_attr *attr, *a;
304 			attr = hostapd_parse_radius_attr(buf + 19);
305 			if (attr == NULL) {
306 				wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s",
307 					   buf + 19);
308 				user = NULL; /* already in the BSS list */
309 				goto failed;
310 			}
311 			if (user->accept_attr == NULL) {
312 				user->accept_attr = attr;
313 			} else {
314 				a = user->accept_attr;
315 				while (a->next)
316 					a = a->next;
317 				a->next = attr;
318 			}
319 			continue;
320 		}
321 #endif /* CONFIG_NO_RADIUS */
322 
323 		user = NULL;
324 
325 		if (buf[0] != '"' && buf[0] != '*') {
326 			wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in "
327 				   "start) on line %d in '%s'", line, fname);
328 			goto failed;
329 		}
330 
331 		user = os_zalloc(sizeof(*user));
332 		if (user == NULL) {
333 			wpa_printf(MSG_ERROR, "EAP user allocation failed");
334 			goto failed;
335 		}
336 		user->force_version = -1;
337 
338 		if (buf[0] == '*') {
339 			pos = buf;
340 		} else {
341 			pos = buf + 1;
342 			start = pos;
343 			while (*pos != '"' && *pos != '\0')
344 				pos++;
345 			if (*pos == '\0') {
346 				wpa_printf(MSG_ERROR, "Invalid EAP identity "
347 					   "(no \" in end) on line %d in '%s'",
348 					   line, fname);
349 				goto failed;
350 			}
351 
352 			user->identity = os_memdup(start, pos - start);
353 			if (user->identity == NULL) {
354 				wpa_printf(MSG_ERROR, "Failed to allocate "
355 					   "memory for EAP identity");
356 				goto failed;
357 			}
358 			user->identity_len = pos - start;
359 
360 			if (pos[0] == '"' && pos[1] == '*') {
361 				user->wildcard_prefix = 1;
362 				pos++;
363 			}
364 		}
365 		pos++;
366 		while (*pos == ' ' || *pos == '\t')
367 			pos++;
368 
369 		if (*pos == '\0') {
370 			wpa_printf(MSG_ERROR, "No EAP method on line %d in "
371 				   "'%s'", line, fname);
372 			goto failed;
373 		}
374 
375 		start = pos;
376 		while (*pos != ' ' && *pos != '\t' && *pos != '\0')
377 			pos++;
378 		if (*pos == '\0') {
379 			pos = NULL;
380 		} else {
381 			*pos = '\0';
382 			pos++;
383 		}
384 		num_methods = 0;
385 		while (*start) {
386 			char *pos3 = os_strchr(start, ',');
387 			if (pos3) {
388 				*pos3++ = '\0';
389 			}
390 			user->methods[num_methods].method =
391 				eap_server_get_type(
392 					start,
393 					&user->methods[num_methods].vendor);
394 			if (user->methods[num_methods].vendor ==
395 			    EAP_VENDOR_IETF &&
396 			    user->methods[num_methods].method == EAP_TYPE_NONE)
397 			{
398 				if (os_strcmp(start, "TTLS-PAP") == 0) {
399 					user->ttls_auth |= EAP_TTLS_AUTH_PAP;
400 					goto skip_eap;
401 				}
402 				if (os_strcmp(start, "TTLS-CHAP") == 0) {
403 					user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
404 					goto skip_eap;
405 				}
406 				if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
407 					user->ttls_auth |=
408 						EAP_TTLS_AUTH_MSCHAP;
409 					goto skip_eap;
410 				}
411 				if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
412 					user->ttls_auth |=
413 						EAP_TTLS_AUTH_MSCHAPV2;
414 					goto skip_eap;
415 				}
416 				if (os_strcmp(start, "MACACL") == 0) {
417 					user->macacl = 1;
418 					goto skip_eap;
419 				}
420 				wpa_printf(MSG_ERROR, "Unsupported EAP type "
421 					   "'%s' on line %d in '%s'",
422 					   start, line, fname);
423 				goto failed;
424 			}
425 
426 			num_methods++;
427 			if (num_methods >= EAP_MAX_METHODS)
428 				break;
429 		skip_eap:
430 			if (pos3 == NULL)
431 				break;
432 			start = pos3;
433 		}
434 		if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) {
435 			wpa_printf(MSG_ERROR, "No EAP types configured on "
436 				   "line %d in '%s'", line, fname);
437 			goto failed;
438 		}
439 
440 		if (pos == NULL)
441 			goto done;
442 
443 		while (*pos == ' ' || *pos == '\t')
444 			pos++;
445 		if (*pos == '\0')
446 			goto done;
447 
448 		if (os_strncmp(pos, "[ver=0]", 7) == 0) {
449 			user->force_version = 0;
450 			goto done;
451 		}
452 
453 		if (os_strncmp(pos, "[ver=1]", 7) == 0) {
454 			user->force_version = 1;
455 			goto done;
456 		}
457 
458 		if (os_strncmp(pos, "[2]", 3) == 0) {
459 			user->phase2 = 1;
460 			goto done;
461 		}
462 
463 		if (*pos == '"') {
464 			pos++;
465 			start = pos;
466 			while (*pos != '"' && *pos != '\0')
467 				pos++;
468 			if (*pos == '\0') {
469 				wpa_printf(MSG_ERROR, "Invalid EAP password "
470 					   "(no \" in end) on line %d in '%s'",
471 					   line, fname);
472 				goto failed;
473 			}
474 
475 			user->password = os_memdup(start, pos - start);
476 			if (user->password == NULL) {
477 				wpa_printf(MSG_ERROR, "Failed to allocate "
478 					   "memory for EAP password");
479 				goto failed;
480 			}
481 			user->password_len = pos - start;
482 
483 			pos++;
484 		} else if (os_strncmp(pos, "hash:", 5) == 0) {
485 			pos += 5;
486 			pos2 = pos;
487 			while (*pos2 != '\0' && *pos2 != ' ' &&
488 			       *pos2 != '\t' && *pos2 != '#')
489 				pos2++;
490 			if (pos2 - pos != 32) {
491 				wpa_printf(MSG_ERROR, "Invalid password hash "
492 					   "on line %d in '%s'", line, fname);
493 				goto failed;
494 			}
495 			user->password = os_malloc(16);
496 			if (user->password == NULL) {
497 				wpa_printf(MSG_ERROR, "Failed to allocate "
498 					   "memory for EAP password hash");
499 				goto failed;
500 			}
501 			if (hexstr2bin(pos, user->password, 16) < 0) {
502 				wpa_printf(MSG_ERROR, "Invalid hash password "
503 					   "on line %d in '%s'", line, fname);
504 				goto failed;
505 			}
506 			user->password_len = 16;
507 			user->password_hash = 1;
508 			pos = pos2;
509 		} else if (os_strncmp(pos, "ssha1:", 6) == 0) {
510 			pos += 6;
511 			if (hostapd_config_eap_user_salted(user, "sha1", 20,
512 							   &pos,
513 							   line, fname) < 0)
514 				goto failed;
515 		} else if (os_strncmp(pos, "ssha256:", 8) == 0) {
516 			pos += 8;
517 			if (hostapd_config_eap_user_salted(user, "sha256", 32,
518 							   &pos,
519 							   line, fname) < 0)
520 				goto failed;
521 		} else if (os_strncmp(pos, "ssha512:", 8) == 0) {
522 			pos += 8;
523 			if (hostapd_config_eap_user_salted(user, "sha512", 64,
524 							   &pos,
525 							   line, fname) < 0)
526 				goto failed;
527 		} else {
528 			pos2 = pos;
529 			while (*pos2 != '\0' && *pos2 != ' ' &&
530 			       *pos2 != '\t' && *pos2 != '#')
531 				pos2++;
532 			if ((pos2 - pos) & 1) {
533 				wpa_printf(MSG_ERROR, "Invalid hex password "
534 					   "on line %d in '%s'", line, fname);
535 				goto failed;
536 			}
537 			user->password = os_malloc((pos2 - pos) / 2);
538 			if (user->password == NULL) {
539 				wpa_printf(MSG_ERROR, "Failed to allocate "
540 					   "memory for EAP password");
541 				goto failed;
542 			}
543 			if (hexstr2bin(pos, user->password,
544 				       (pos2 - pos) / 2) < 0) {
545 				wpa_printf(MSG_ERROR, "Invalid hex password "
546 					   "on line %d in '%s'", line, fname);
547 				goto failed;
548 			}
549 			user->password_len = (pos2 - pos) / 2;
550 			pos = pos2;
551 		}
552 
553 		while (*pos == ' ' || *pos == '\t')
554 			pos++;
555 		if (os_strncmp(pos, "[2]", 3) == 0) {
556 			user->phase2 = 1;
557 		}
558 
559 	done:
560 		if (tail == NULL) {
561 			tail = new_user = user;
562 		} else {
563 			tail->next = user;
564 			tail = user;
565 		}
566 		continue;
567 
568 	failed:
569 		if (user)
570 			hostapd_config_free_eap_user(user);
571 		ret = -1;
572 		break;
573 	}
574 
575 	fclose(f);
576 
577 	if (ret == 0) {
578 		hostapd_config_free_eap_users(conf->eap_user);
579 		conf->eap_user = new_user;
580 	} else {
581 		hostapd_config_free_eap_users(new_user);
582 	}
583 
584 	return ret;
585 }
586 
587 #endif /* EAP_SERVER */
588 
589 
590 #ifndef CONFIG_NO_RADIUS
591 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)592 hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
593 				int *num_server, const char *val, int def_port,
594 				struct hostapd_radius_server **curr_serv)
595 {
596 	struct hostapd_radius_server *nserv;
597 	int ret;
598 	static int server_index = 1;
599 
600 	nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv));
601 	if (nserv == NULL)
602 		return -1;
603 
604 	*server = nserv;
605 	nserv = &nserv[*num_server];
606 	(*num_server)++;
607 	(*curr_serv) = nserv;
608 
609 	os_memset(nserv, 0, sizeof(*nserv));
610 	nserv->port = def_port;
611 	ret = hostapd_parse_ip_addr(val, &nserv->addr);
612 	nserv->index = server_index++;
613 
614 	return ret;
615 }
616 
617 
618 
hostapd_parse_das_client(struct hostapd_bss_config * bss,char * val)619 static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
620 {
621 	char *secret;
622 
623 	secret = os_strchr(val, ' ');
624 	if (secret == NULL)
625 		return -1;
626 
627 	*secret++ = '\0';
628 
629 	if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
630 		return -1;
631 
632 	os_free(bss->radius_das_shared_secret);
633 	bss->radius_das_shared_secret = (u8 *) os_strdup(secret);
634 	if (bss->radius_das_shared_secret == NULL)
635 		return -1;
636 	bss->radius_das_shared_secret_len = os_strlen(secret);
637 
638 	return 0;
639 }
640 #endif /* CONFIG_NO_RADIUS */
641 
642 
hostapd_config_parse_key_mgmt(int line,const char * value)643 static int hostapd_config_parse_key_mgmt(int line, const char *value)
644 {
645 	int val = 0, last;
646 	char *start, *end, *buf;
647 
648 	buf = os_strdup(value);
649 	if (buf == NULL)
650 		return -1;
651 	start = buf;
652 
653 	while (*start != '\0') {
654 		while (*start == ' ' || *start == '\t')
655 			start++;
656 		if (*start == '\0')
657 			break;
658 		end = start;
659 		while (*end != ' ' && *end != '\t' && *end != '\0')
660 			end++;
661 		last = *end == '\0';
662 		*end = '\0';
663 		if (os_strcmp(start, "WPA-PSK") == 0)
664 			val |= WPA_KEY_MGMT_PSK;
665 		else if (os_strcmp(start, "WPA-EAP") == 0)
666 			val |= WPA_KEY_MGMT_IEEE8021X;
667 #ifdef CONFIG_IEEE80211R_AP
668 		else if (os_strcmp(start, "FT-PSK") == 0)
669 			val |= WPA_KEY_MGMT_FT_PSK;
670 		else if (os_strcmp(start, "FT-EAP") == 0)
671 			val |= WPA_KEY_MGMT_FT_IEEE8021X;
672 #ifdef CONFIG_SHA384
673 		else if (os_strcmp(start, "FT-EAP-SHA384") == 0)
674 			val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
675 #endif /* CONFIG_SHA384 */
676 #endif /* CONFIG_IEEE80211R_AP */
677 #ifdef CONFIG_SHA384
678 		else if (os_strcmp(start, "WPA-EAP-SHA384") == 0)
679 			val |= WPA_KEY_MGMT_IEEE8021X_SHA384;
680 #endif /* CONFIG_SHA384 */
681 		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
682 			val |= WPA_KEY_MGMT_PSK_SHA256;
683 		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
684 			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
685 #ifdef CONFIG_SAE
686 		else if (os_strcmp(start, "SAE") == 0)
687 			val |= WPA_KEY_MGMT_SAE;
688 		else if (os_strcmp(start, "SAE-EXT-KEY") == 0)
689 			val |= WPA_KEY_MGMT_SAE_EXT_KEY;
690 		else if (os_strcmp(start, "FT-SAE") == 0)
691 			val |= WPA_KEY_MGMT_FT_SAE;
692 		else if (os_strcmp(start, "FT-SAE-EXT-KEY") == 0)
693 			val |= WPA_KEY_MGMT_FT_SAE_EXT_KEY;
694 #endif /* CONFIG_SAE */
695 #ifdef CONFIG_SUITEB
696 		else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
697 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
698 #endif /* CONFIG_SUITEB */
699 #ifdef CONFIG_SUITEB192
700 		else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
701 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
702 #endif /* CONFIG_SUITEB192 */
703 #ifdef CONFIG_FILS
704 		else if (os_strcmp(start, "FILS-SHA256") == 0)
705 			val |= WPA_KEY_MGMT_FILS_SHA256;
706 		else if (os_strcmp(start, "FILS-SHA384") == 0)
707 			val |= WPA_KEY_MGMT_FILS_SHA384;
708 #ifdef CONFIG_IEEE80211R_AP
709 		else if (os_strcmp(start, "FT-FILS-SHA256") == 0)
710 			val |= WPA_KEY_MGMT_FT_FILS_SHA256;
711 		else if (os_strcmp(start, "FT-FILS-SHA384") == 0)
712 			val |= WPA_KEY_MGMT_FT_FILS_SHA384;
713 #endif /* CONFIG_IEEE80211R_AP */
714 #endif /* CONFIG_FILS */
715 #ifdef CONFIG_OWE
716 		else if (os_strcmp(start, "OWE") == 0)
717 			val |= WPA_KEY_MGMT_OWE;
718 #endif /* CONFIG_OWE */
719 #ifdef CONFIG_DPP
720 		else if (os_strcmp(start, "DPP") == 0)
721 			val |= WPA_KEY_MGMT_DPP;
722 #endif /* CONFIG_DPP */
723 #ifdef CONFIG_HS20
724 		else if (os_strcmp(start, "OSEN") == 0)
725 			val |= WPA_KEY_MGMT_OSEN;
726 #endif /* CONFIG_HS20 */
727 #ifdef CONFIG_PASN
728 		else if (os_strcmp(start, "PASN") == 0)
729 			val |= WPA_KEY_MGMT_PASN;
730 #endif /* CONFIG_PASN */
731 		else {
732 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
733 				   line, start);
734 			os_free(buf);
735 			return -1;
736 		}
737 
738 		if (last)
739 			break;
740 		start = end + 1;
741 	}
742 
743 	os_free(buf);
744 	if (val == 0) {
745 		wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values "
746 			   "configured.", line);
747 		return -1;
748 	}
749 
750 	return val;
751 }
752 
753 
hostapd_config_parse_cipher(int line,const char * value)754 static int hostapd_config_parse_cipher(int line, const char *value)
755 {
756 	int val = wpa_parse_cipher(value);
757 	if (val < 0) {
758 		wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
759 			   line, value);
760 		return -1;
761 	}
762 	if (val == 0) {
763 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
764 			   line);
765 		return -1;
766 	}
767 	return val;
768 }
769 
770 
771 #ifdef CONFIG_WEP
hostapd_config_read_wep(struct hostapd_wep_keys * wep,int keyidx,char * val)772 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
773 				   char *val)
774 {
775 	size_t len = os_strlen(val);
776 
777 	if (keyidx < 0 || keyidx > 3)
778 		return -1;
779 
780 	if (len == 0) {
781 		int i, set = 0;
782 
783 		bin_clear_free(wep->key[keyidx], wep->len[keyidx]);
784 		wep->key[keyidx] = NULL;
785 		wep->len[keyidx] = 0;
786 		for (i = 0; i < NUM_WEP_KEYS; i++) {
787 			if (wep->key[i])
788 				set++;
789 		}
790 		if (!set)
791 			wep->keys_set = 0;
792 		return 0;
793 	}
794 
795 	if (wep->key[keyidx] != NULL)
796 		return -1;
797 
798 	if (val[0] == '"') {
799 		if (len < 2 || val[len - 1] != '"')
800 			return -1;
801 		len -= 2;
802 		wep->key[keyidx] = os_memdup(val + 1, len);
803 		if (wep->key[keyidx] == NULL)
804 			return -1;
805 		wep->len[keyidx] = len;
806 	} else {
807 		if (len & 1)
808 			return -1;
809 		len /= 2;
810 		wep->key[keyidx] = os_malloc(len);
811 		if (wep->key[keyidx] == NULL)
812 			return -1;
813 		wep->len[keyidx] = len;
814 		if (hexstr2bin(val, wep->key[keyidx], len) < 0)
815 			return -1;
816 	}
817 
818 	wep->keys_set++;
819 
820 	return 0;
821 }
822 #endif /* CONFIG_WEP */
823 
824 
hostapd_parse_chanlist(struct hostapd_config * conf,char * val)825 static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
826 {
827 	char *pos;
828 
829 	/* for backwards compatibility, translate ' ' in conf str to ',' */
830 	pos = val;
831 	while (pos) {
832 		pos = os_strchr(pos, ' ');
833 		if (pos)
834 			*pos++ = ',';
835 	}
836 	if (freq_range_list_parse(&conf->acs_ch_list, val))
837 		return -1;
838 
839 	return 0;
840 }
841 
842 
hostapd_parse_intlist(int ** int_list,char * val)843 static int hostapd_parse_intlist(int **int_list, char *val)
844 {
845 	int *list;
846 	int count;
847 	char *pos, *end;
848 
849 	os_free(*int_list);
850 	*int_list = NULL;
851 
852 	pos = val;
853 	count = 0;
854 	while (*pos != '\0') {
855 		if (*pos == ' ')
856 			count++;
857 		pos++;
858 	}
859 
860 	list = os_malloc(sizeof(int) * (count + 2));
861 	if (list == NULL)
862 		return -1;
863 	pos = val;
864 	count = 0;
865 	while (*pos != '\0') {
866 		end = os_strchr(pos, ' ');
867 		if (end)
868 			*end = '\0';
869 
870 		list[count++] = atoi(pos);
871 		if (!end)
872 			break;
873 		pos = end + 1;
874 	}
875 	list[count] = -1;
876 
877 	*int_list = list;
878 	return 0;
879 }
880 
881 
hostapd_config_bss(struct hostapd_config * conf,const char * ifname)882 static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
883 {
884 	struct hostapd_bss_config **all, *bss;
885 
886 	if (*ifname == '\0')
887 		return -1;
888 
889 	all = os_realloc_array(conf->bss, conf->num_bss + 1,
890 			       sizeof(struct hostapd_bss_config *));
891 	if (all == NULL) {
892 		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
893 			   "multi-BSS entry");
894 		return -1;
895 	}
896 	conf->bss = all;
897 
898 	bss = os_zalloc(sizeof(*bss));
899 	if (bss == NULL)
900 		return -1;
901 	bss->radius = os_zalloc(sizeof(*bss->radius));
902 	if (bss->radius == NULL) {
903 		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
904 			   "multi-BSS RADIUS data");
905 		os_free(bss);
906 		return -1;
907 	}
908 
909 	conf->bss[conf->num_bss++] = bss;
910 	conf->last_bss = bss;
911 
912 	hostapd_config_defaults_bss(bss);
913 	os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
914 	os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
915 
916 	return 0;
917 }
918 
919 
920 #ifdef CONFIG_IEEE80211R_AP
921 
rkh_derive_key(const char * pos,u8 * key,size_t key_len)922 static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
923 {
924 	u8 oldkey[16];
925 	int ret;
926 
927 	if (!hexstr2bin(pos, key, key_len))
928 		return 0;
929 
930 	/* Try to use old short key for backwards compatibility */
931 	if (hexstr2bin(pos, oldkey, sizeof(oldkey)))
932 		return -1;
933 
934 	ret = hmac_sha256_kdf(oldkey, sizeof(oldkey), "FT OLDKEY", NULL, 0,
935 			      key, key_len);
936 	os_memset(oldkey, 0, sizeof(oldkey));
937 	return ret;
938 }
939 
940 
add_r0kh(struct hostapd_bss_config * bss,char * value)941 static int add_r0kh(struct hostapd_bss_config *bss, char *value)
942 {
943 	struct ft_remote_r0kh *r0kh;
944 	char *pos, *next;
945 
946 	r0kh = os_zalloc(sizeof(*r0kh));
947 	if (r0kh == NULL)
948 		return -1;
949 
950 	/* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
951 	pos = value;
952 	next = os_strchr(pos, ' ');
953 	if (next)
954 		*next++ = '\0';
955 	if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
956 		wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", anonymize_common(pos));
957 		os_free(r0kh);
958 		return -1;
959 	}
960 
961 	pos = next;
962 	next = os_strchr(pos, ' ');
963 	if (next)
964 		*next++ = '\0';
965 	if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
966 		wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos);
967 		os_free(r0kh);
968 		return -1;
969 	}
970 	r0kh->id_len = next - pos - 1;
971 	os_memcpy(r0kh->id, pos, r0kh->id_len);
972 
973 	pos = next;
974 	if (rkh_derive_key(pos, r0kh->key, sizeof(r0kh->key)) < 0) {
975 		wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos);
976 		os_free(r0kh);
977 		return -1;
978 	}
979 
980 	r0kh->next = bss->r0kh_list;
981 	bss->r0kh_list = r0kh;
982 
983 	return 0;
984 }
985 
986 
add_r1kh(struct hostapd_bss_config * bss,char * value)987 static int add_r1kh(struct hostapd_bss_config *bss, char *value)
988 {
989 	struct ft_remote_r1kh *r1kh;
990 	char *pos, *next;
991 
992 	r1kh = os_zalloc(sizeof(*r1kh));
993 	if (r1kh == NULL)
994 		return -1;
995 
996 	/* 02:01:02:03:04:05 02:01:02:03:04:05
997 	 * 000102030405060708090a0b0c0d0e0f */
998 	pos = value;
999 	next = os_strchr(pos, ' ');
1000 	if (next)
1001 		*next++ = '\0';
1002 	if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
1003 		wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", anonymize_common(pos));
1004 		os_free(r1kh);
1005 		return -1;
1006 	}
1007 
1008 	pos = next;
1009 	next = os_strchr(pos, ' ');
1010 	if (next)
1011 		*next++ = '\0';
1012 	if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
1013 		wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos);
1014 		os_free(r1kh);
1015 		return -1;
1016 	}
1017 
1018 	pos = next;
1019 	if (rkh_derive_key(pos, r1kh->key, sizeof(r1kh->key)) < 0) {
1020 		wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos);
1021 		os_free(r1kh);
1022 		return -1;
1023 	}
1024 
1025 	r1kh->next = bss->r1kh_list;
1026 	bss->r1kh_list = r1kh;
1027 
1028 	return 0;
1029 }
1030 
1031 
hostapd_config_read_rxkh_file(struct hostapd_bss_config * conf,const char * fname)1032 int hostapd_config_read_rxkh_file(struct hostapd_bss_config *conf,
1033 				  const char *fname)
1034 {
1035 	FILE *f;
1036 	char buf[256], *pos;
1037 	int line = 0, errors = 0;
1038 
1039 	if (!fname)
1040 		return 0;
1041 
1042 	f = fopen(fname, "r");
1043 	if (!f) {
1044 		wpa_printf(MSG_ERROR, "rxkh file '%s' not found.", fname);
1045 		return -1;
1046 	}
1047 
1048 	while (fgets(buf, sizeof(buf), f)) {
1049 		line++;
1050 
1051 		if (buf[0] == '#')
1052 			continue;
1053 		pos = buf;
1054 		while (*pos != '\0') {
1055 			if (*pos == '\n') {
1056 				*pos = '\0';
1057 				break;
1058 			}
1059 			pos++;
1060 		}
1061 		if (buf[0] == '\0')
1062 			continue;
1063 
1064 		pos = os_strchr(buf, '=');
1065 		if (!pos) {
1066 			wpa_printf(MSG_ERROR, "Line %d: Invalid line '%s'",
1067 				   line, buf);
1068 			errors++;
1069 			continue;
1070 		}
1071 		*pos = '\0';
1072 		pos++;
1073 
1074 		if (os_strcmp(buf, "r0kh") == 0) {
1075 			if (add_r0kh(conf, pos) < 0) {
1076 				wpa_printf(MSG_ERROR,
1077 					   "Line %d: Invalid r0kh '%s'",
1078 					   line, pos);
1079 				errors++;
1080 			}
1081 		} else if (os_strcmp(buf, "r1kh") == 0) {
1082 			if (add_r1kh(conf, pos) < 0) {
1083 				wpa_printf(MSG_ERROR,
1084 					   "Line %d: Invalid r1kh '%s'",
1085 					   line, pos);
1086 				errors++;
1087 			}
1088 		}
1089 	}
1090 
1091 	fclose(f);
1092 
1093 	if (errors) {
1094 		wpa_printf(MSG_ERROR,
1095 			   "%d errors in configuring RxKHs from '%s'",
1096 			   errors, fname);
1097 		return -1;
1098 	}
1099 	return 0;
1100 }
1101 
1102 #endif /* CONFIG_IEEE80211R_AP */
1103 
1104 
hostapd_config_ht_capab(struct hostapd_config * conf,const char * capab)1105 static int hostapd_config_ht_capab(struct hostapd_config *conf,
1106 				   const char *capab)
1107 {
1108 	if (os_strstr(capab, "[LDPC]"))
1109 		conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
1110 	if (os_strstr(capab, "[HT40-]")) {
1111 		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1112 		conf->secondary_channel = -1;
1113 	}
1114 	if (os_strstr(capab, "[HT40+]")) {
1115 		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1116 		conf->secondary_channel = 1;
1117 	}
1118 	if (os_strstr(capab, "[HT40+]") && os_strstr(capab, "[HT40-]")) {
1119 		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
1120 		conf->ht40_plus_minus_allowed = 1;
1121 	}
1122 	if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
1123 		conf->secondary_channel = 0;
1124 	if (os_strstr(capab, "[HT20]"))
1125 		conf->ht20_set_flag = 1;
1126 	if (os_strstr(capab, "[GF]"))
1127 		conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
1128 	if (os_strstr(capab, "[SHORT-GI-20]"))
1129 		conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
1130 	if (os_strstr(capab, "[SHORT-GI-40]"))
1131 		conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
1132 	if (os_strstr(capab, "[TX-STBC]"))
1133 		conf->ht_capab |= HT_CAP_INFO_TX_STBC;
1134 	if (os_strstr(capab, "[RX-STBC1]")) {
1135 		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1136 		conf->ht_capab |= HT_CAP_INFO_RX_STBC_1;
1137 	}
1138 	if (os_strstr(capab, "[RX-STBC12]")) {
1139 		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1140 		conf->ht_capab |= HT_CAP_INFO_RX_STBC_12;
1141 	}
1142 	if (os_strstr(capab, "[RX-STBC123]")) {
1143 		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
1144 		conf->ht_capab |= HT_CAP_INFO_RX_STBC_123;
1145 	}
1146 	if (os_strstr(capab, "[DELAYED-BA]"))
1147 		conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
1148 	if (os_strstr(capab, "[MAX-AMSDU-7935]"))
1149 		conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
1150 	if (os_strstr(capab, "[DSSS_CCK-40]"))
1151 		conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
1152 	if (os_strstr(capab, "[40-INTOLERANT]"))
1153 		conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
1154 	if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
1155 		conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
1156 
1157 	return 0;
1158 }
1159 
1160 
1161 #ifdef CONFIG_IEEE80211AC
hostapd_config_vht_capab(struct hostapd_config * conf,const char * capab)1162 static int hostapd_config_vht_capab(struct hostapd_config *conf,
1163 				    const char *capab)
1164 {
1165 	if (os_strstr(capab, "[MAX-MPDU-7991]"))
1166 		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
1167 	if (os_strstr(capab, "[MAX-MPDU-11454]"))
1168 		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
1169 	if (os_strstr(capab, "[VHT160]"))
1170 		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1171 	if (os_strstr(capab, "[VHT160-80PLUS80]"))
1172 		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1173 	if (os_strstr(capab, "[RXLDPC]"))
1174 		conf->vht_capab |= VHT_CAP_RXLDPC;
1175 	if (os_strstr(capab, "[SHORT-GI-80]"))
1176 		conf->vht_capab |= VHT_CAP_SHORT_GI_80;
1177 	if (os_strstr(capab, "[SHORT-GI-160]"))
1178 		conf->vht_capab |= VHT_CAP_SHORT_GI_160;
1179 	if (os_strstr(capab, "[TX-STBC-2BY1]"))
1180 		conf->vht_capab |= VHT_CAP_TXSTBC;
1181 	if (os_strstr(capab, "[RX-STBC-1]"))
1182 		conf->vht_capab |= VHT_CAP_RXSTBC_1;
1183 	if (os_strstr(capab, "[RX-STBC-12]"))
1184 		conf->vht_capab |= VHT_CAP_RXSTBC_2;
1185 	if (os_strstr(capab, "[RX-STBC-123]"))
1186 		conf->vht_capab |= VHT_CAP_RXSTBC_3;
1187 	if (os_strstr(capab, "[RX-STBC-1234]"))
1188 		conf->vht_capab |= VHT_CAP_RXSTBC_4;
1189 	if (os_strstr(capab, "[SU-BEAMFORMER]"))
1190 		conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE;
1191 	if (os_strstr(capab, "[SU-BEAMFORMEE]"))
1192 		conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1193 	if (os_strstr(capab, "[BF-ANTENNA-2]") &&
1194 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
1195 		conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1196 	if (os_strstr(capab, "[BF-ANTENNA-3]") &&
1197 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
1198 		conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1199 	if (os_strstr(capab, "[BF-ANTENNA-4]") &&
1200 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
1201 		conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1202 	if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
1203 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
1204 		conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
1205 	if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") &&
1206 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
1207 		conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
1208 	if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") &&
1209 	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
1210 		conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
1211 	if (os_strstr(capab, "[MU-BEAMFORMER]"))
1212 		conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
1213 	if (os_strstr(capab, "[VHT-TXOP-PS]"))
1214 		conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
1215 	if (os_strstr(capab, "[HTC-VHT]"))
1216 		conf->vht_capab |= VHT_CAP_HTC_VHT;
1217 	if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]"))
1218 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
1219 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]"))
1220 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6;
1221 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]"))
1222 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5;
1223 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]"))
1224 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4;
1225 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]"))
1226 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3;
1227 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]"))
1228 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2;
1229 	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]"))
1230 		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1;
1231 	if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
1232 	    (conf->vht_capab & VHT_CAP_HTC_VHT))
1233 		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
1234 	if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
1235 	    (conf->vht_capab & VHT_CAP_HTC_VHT))
1236 		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
1237 	if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
1238 		conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
1239 	if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
1240 		conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
1241 	return 0;
1242 }
1243 #endif /* CONFIG_IEEE80211AC */
1244 
1245 
1246 #ifdef CONFIG_IEEE80211AX
1247 
find_bit_offset(u8 val)1248 static u8 find_bit_offset(u8 val)
1249 {
1250 	u8 res = 0;
1251 
1252 	for (; val; val >>= 1) {
1253 		if (val & 1)
1254 			break;
1255 		res++;
1256 	}
1257 
1258 	return res;
1259 }
1260 
1261 
set_he_cap(int val,u8 mask)1262 static u8 set_he_cap(int val, u8 mask)
1263 {
1264 	return (u8) (mask & (val << find_bit_offset(mask)));
1265 }
1266 
1267 
hostapd_parse_he_srg_bitmap(u8 * bitmap,char * val)1268 static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val)
1269 {
1270 	int bitpos;
1271 	char *pos, *end;
1272 
1273 	os_memset(bitmap, 0, 8);
1274 	pos = val;
1275 	while (*pos != '\0') {
1276 		end = os_strchr(pos, ' ');
1277 		if (end)
1278 			*end = '\0';
1279 
1280 		bitpos = atoi(pos);
1281 		if (bitpos < 0 || bitpos > 64)
1282 			return -1;
1283 
1284 		bitmap[bitpos / 8] |= BIT(bitpos % 8);
1285 		if (!end)
1286 			break;
1287 		pos = end + 1;
1288 	}
1289 
1290 	return 0;
1291 }
1292 
1293 #endif /* CONFIG_IEEE80211AX */
1294 
1295 
1296 #ifdef CONFIG_INTERWORKING
parse_roaming_consortium(struct hostapd_bss_config * bss,char * pos,int line)1297 static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
1298 				    int line)
1299 {
1300 	size_t len = os_strlen(pos);
1301 	u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
1302 
1303 	struct hostapd_roaming_consortium *rc;
1304 
1305 	if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
1306 	    hexstr2bin(pos, oi, len / 2)) {
1307 		wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
1308 			   "'%s'", line, pos);
1309 		return -1;
1310 	}
1311 	len /= 2;
1312 
1313 	rc = os_realloc_array(bss->roaming_consortium,
1314 			      bss->roaming_consortium_count + 1,
1315 			      sizeof(struct hostapd_roaming_consortium));
1316 	if (rc == NULL)
1317 		return -1;
1318 
1319 	os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
1320 	rc[bss->roaming_consortium_count].len = len;
1321 
1322 	bss->roaming_consortium = rc;
1323 	bss->roaming_consortium_count++;
1324 
1325 	return 0;
1326 }
1327 
1328 
parse_lang_string(struct hostapd_lang_string ** array,unsigned int * count,char * pos)1329 static int parse_lang_string(struct hostapd_lang_string **array,
1330 			     unsigned int *count, char *pos)
1331 {
1332 	char *sep, *str = NULL;
1333 	size_t clen, nlen, slen;
1334 	struct hostapd_lang_string *ls;
1335 	int ret = -1;
1336 
1337 	if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) {
1338 		str = wpa_config_parse_string(pos, &slen);
1339 		if (!str)
1340 			return -1;
1341 		pos = str;
1342 	}
1343 
1344 	sep = os_strchr(pos, ':');
1345 	if (sep == NULL)
1346 		goto fail;
1347 	*sep++ = '\0';
1348 
1349 	clen = os_strlen(pos);
1350 	if (clen < 2 || clen > sizeof(ls->lang))
1351 		goto fail;
1352 	nlen = os_strlen(sep);
1353 	if (nlen > 252)
1354 		goto fail;
1355 
1356 	ls = os_realloc_array(*array, *count + 1,
1357 			      sizeof(struct hostapd_lang_string));
1358 	if (ls == NULL)
1359 		goto fail;
1360 
1361 	*array = ls;
1362 	ls = &(*array)[*count];
1363 	(*count)++;
1364 
1365 	os_memset(ls->lang, 0, sizeof(ls->lang));
1366 	os_memcpy(ls->lang, pos, clen);
1367 	ls->name_len = nlen;
1368 	os_memcpy(ls->name, sep, nlen);
1369 
1370 	ret = 0;
1371 fail:
1372 	os_free(str);
1373 	return ret;
1374 }
1375 
1376 
parse_venue_name(struct hostapd_bss_config * bss,char * pos,int line)1377 static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
1378 			    int line)
1379 {
1380 	if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) {
1381 		wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
1382 			   line, pos);
1383 		return -1;
1384 	}
1385 	return 0;
1386 }
1387 
1388 
parse_venue_url(struct hostapd_bss_config * bss,char * pos,int line)1389 static int parse_venue_url(struct hostapd_bss_config *bss, char *pos,
1390 			    int line)
1391 {
1392 	char *sep;
1393 	size_t nlen;
1394 	struct hostapd_venue_url *url;
1395 	int ret = -1;
1396 
1397 	sep = os_strchr(pos, ':');
1398 	if (!sep)
1399 		goto fail;
1400 	*sep++ = '\0';
1401 
1402 	nlen = os_strlen(sep);
1403 	if (nlen > 254)
1404 		goto fail;
1405 
1406 	url = os_realloc_array(bss->venue_url, bss->venue_url_count + 1,
1407 			       sizeof(struct hostapd_venue_url));
1408 	if (!url)
1409 		goto fail;
1410 
1411 	bss->venue_url = url;
1412 	url = &bss->venue_url[bss->venue_url_count++];
1413 
1414 	url->venue_number = atoi(pos);
1415 	url->url_len = nlen;
1416 	os_memcpy(url->url, sep, nlen);
1417 
1418 	ret = 0;
1419 fail:
1420 	if (ret)
1421 		wpa_printf(MSG_ERROR, "Line %d: Invalid venue_url '%s'",
1422 			   line, pos);
1423 	return ret;
1424 }
1425 
1426 
parse_3gpp_cell_net(struct hostapd_bss_config * bss,char * buf,int line)1427 static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
1428 			       int line)
1429 {
1430 	size_t count;
1431 	char *pos;
1432 	u8 *info = NULL, *ipos;
1433 
1434 	/* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
1435 
1436 	count = 1;
1437 	for (pos = buf; *pos; pos++) {
1438 		if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',')
1439 			goto fail;
1440 		if (*pos == ';')
1441 			count++;
1442 	}
1443 	if (1 + count * 3 > 0x7f)
1444 		goto fail;
1445 
1446 	info = os_zalloc(2 + 3 + count * 3);
1447 	if (info == NULL)
1448 		return -1;
1449 
1450 	ipos = info;
1451 	*ipos++ = 0; /* GUD - Version 1 */
1452 	*ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
1453 	*ipos++ = 0; /* PLMN List IEI */
1454 	/* ext(b8) | Length of PLMN List value contents(b7..1) */
1455 	*ipos++ = 1 + count * 3;
1456 	*ipos++ = count; /* Number of PLMNs */
1457 
1458 	pos = buf;
1459 	while (pos && *pos) {
1460 		char *mcc, *mnc;
1461 		size_t mnc_len;
1462 
1463 		mcc = pos;
1464 		mnc = os_strchr(pos, ',');
1465 		if (mnc == NULL)
1466 			goto fail;
1467 		*mnc++ = '\0';
1468 		pos = os_strchr(mnc, ';');
1469 		if (pos)
1470 			*pos++ = '\0';
1471 
1472 		mnc_len = os_strlen(mnc);
1473 		if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3))
1474 			goto fail;
1475 
1476 		/* BC coded MCC,MNC */
1477 		/* MCC digit 2 | MCC digit 1 */
1478 		*ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
1479 		/* MNC digit 3 | MCC digit 3 */
1480 		*ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
1481 			(mcc[2] - '0');
1482 		/* MNC digit 2 | MNC digit 1 */
1483 		*ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
1484 	}
1485 
1486 	os_free(bss->anqp_3gpp_cell_net);
1487 	bss->anqp_3gpp_cell_net = info;
1488 	bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
1489 	wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
1490 		    bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
1491 
1492 	return 0;
1493 
1494 fail:
1495 	wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s",
1496 		   line, buf);
1497 	os_free(info);
1498 	return -1;
1499 }
1500 
1501 
parse_nai_realm(struct hostapd_bss_config * bss,char * buf,int line)1502 static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line)
1503 {
1504 	struct hostapd_nai_realm_data *realm;
1505 	size_t i, j, len;
1506 	int *offsets;
1507 	char *pos, *end, *rpos;
1508 
1509 	offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS,
1510 			    sizeof(int));
1511 	if (offsets == NULL)
1512 		return -1;
1513 
1514 	for (i = 0; i < bss->nai_realm_count; i++) {
1515 		realm = &bss->nai_realm_data[i];
1516 		for (j = 0; j < MAX_NAI_REALMS; j++) {
1517 			offsets[i * MAX_NAI_REALMS + j] =
1518 				realm->realm[j] ?
1519 				realm->realm[j] - realm->realm_buf : -1;
1520 		}
1521 	}
1522 
1523 	realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1,
1524 				 sizeof(struct hostapd_nai_realm_data));
1525 	if (realm == NULL) {
1526 		os_free(offsets);
1527 		return -1;
1528 	}
1529 	bss->nai_realm_data = realm;
1530 
1531 	/* patch the pointers after realloc */
1532 	for (i = 0; i < bss->nai_realm_count; i++) {
1533 		realm = &bss->nai_realm_data[i];
1534 		for (j = 0; j < MAX_NAI_REALMS; j++) {
1535 			int offs = offsets[i * MAX_NAI_REALMS + j];
1536 			if (offs >= 0)
1537 				realm->realm[j] = realm->realm_buf + offs;
1538 			else
1539 				realm->realm[j] = NULL;
1540 		}
1541 	}
1542 	os_free(offsets);
1543 
1544 	realm = &bss->nai_realm_data[bss->nai_realm_count];
1545 	os_memset(realm, 0, sizeof(*realm));
1546 
1547 	pos = buf;
1548 	realm->encoding = atoi(pos);
1549 	pos = os_strchr(pos, ',');
1550 	if (pos == NULL)
1551 		goto fail;
1552 	pos++;
1553 
1554 	end = os_strchr(pos, ',');
1555 	if (end) {
1556 		len = end - pos;
1557 		*end = '\0';
1558 	} else {
1559 		len = os_strlen(pos);
1560 	}
1561 
1562 	if (len > MAX_NAI_REALMLEN) {
1563 		wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d "
1564 			   "characters)", (int) len, MAX_NAI_REALMLEN);
1565 		goto fail;
1566 	}
1567 	os_memcpy(realm->realm_buf, pos, len);
1568 
1569 	if (end)
1570 		pos = end + 1;
1571 	else
1572 		pos = NULL;
1573 
1574 	while (pos && *pos) {
1575 		struct hostapd_nai_realm_eap *eap;
1576 
1577 		if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) {
1578 			wpa_printf(MSG_ERROR, "Too many EAP methods");
1579 			goto fail;
1580 		}
1581 
1582 		eap = &realm->eap_method[realm->eap_method_count];
1583 		realm->eap_method_count++;
1584 
1585 		end = os_strchr(pos, ',');
1586 		if (end == NULL)
1587 			end = pos + os_strlen(pos);
1588 
1589 		eap->eap_method = atoi(pos);
1590 		for (;;) {
1591 			pos = os_strchr(pos, '[');
1592 			if (pos == NULL || pos > end)
1593 				break;
1594 			pos++;
1595 			if (eap->num_auths >= MAX_NAI_AUTH_TYPES) {
1596 				wpa_printf(MSG_ERROR, "Too many auth params");
1597 				goto fail;
1598 			}
1599 			eap->auth_id[eap->num_auths] = atoi(pos);
1600 			pos = os_strchr(pos, ':');
1601 			if (pos == NULL || pos > end)
1602 				goto fail;
1603 			pos++;
1604 			eap->auth_val[eap->num_auths] = atoi(pos);
1605 			pos = os_strchr(pos, ']');
1606 			if (pos == NULL || pos > end)
1607 				goto fail;
1608 			pos++;
1609 			eap->num_auths++;
1610 		}
1611 
1612 		if (*end != ',')
1613 			break;
1614 
1615 		pos = end + 1;
1616 	}
1617 
1618 	/* Split realm list into null terminated realms */
1619 	rpos = realm->realm_buf;
1620 	i = 0;
1621 	while (*rpos) {
1622 		if (i >= MAX_NAI_REALMS) {
1623 			wpa_printf(MSG_ERROR, "Too many realms");
1624 			goto fail;
1625 		}
1626 		realm->realm[i++] = rpos;
1627 		rpos = os_strchr(rpos, ';');
1628 		if (rpos == NULL)
1629 			break;
1630 		*rpos++ = '\0';
1631 	}
1632 
1633 	bss->nai_realm_count++;
1634 
1635 	return 0;
1636 
1637 fail:
1638 	wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf);
1639 	return -1;
1640 }
1641 
1642 
parse_anqp_elem(struct hostapd_bss_config * bss,char * buf,int line)1643 static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
1644 {
1645 	char *delim;
1646 	u16 infoid;
1647 	size_t len;
1648 	struct wpabuf *payload;
1649 	struct anqp_element *elem;
1650 
1651 	delim = os_strchr(buf, ':');
1652 	if (!delim)
1653 		return -1;
1654 	delim++;
1655 	infoid = atoi(buf);
1656 	len = os_strlen(delim);
1657 	if (len & 1)
1658 		return -1;
1659 	len /= 2;
1660 	payload = wpabuf_alloc(len);
1661 	if (!payload)
1662 		return -1;
1663 	if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) {
1664 		wpabuf_free(payload);
1665 		return -1;
1666 	}
1667 
1668 	dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) {
1669 		if (elem->infoid == infoid) {
1670 			/* Update existing entry */
1671 			wpabuf_free(elem->payload);
1672 			elem->payload = payload;
1673 			return 0;
1674 		}
1675 	}
1676 
1677 	/* Add a new entry */
1678 	elem = os_zalloc(sizeof(*elem));
1679 	if (!elem) {
1680 		wpabuf_free(payload);
1681 		return -1;
1682 	}
1683 	elem->infoid = infoid;
1684 	elem->payload = payload;
1685 	dl_list_add(&bss->anqp_elem, &elem->list);
1686 
1687 	return 0;
1688 }
1689 
1690 #endif /* CONFIG_INTERWORKING */
1691 
1692 
parse_qos_map_set(struct hostapd_bss_config * bss,char * buf,int line)1693 static int parse_qos_map_set(struct hostapd_bss_config *bss,
1694 			     char *buf, int line)
1695 {
1696 	u8 qos_map_set[16 + 2 * 21], count = 0;
1697 	char *pos = buf;
1698 	int val;
1699 
1700 	for (;;) {
1701 		if (count == sizeof(qos_map_set)) {
1702 			wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set "
1703 				   "parameters '%s'", line, buf);
1704 			return -1;
1705 		}
1706 
1707 		val = atoi(pos);
1708 		if (val > 255 || val < 0) {
1709 			wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set "
1710 				   "'%s'", line, buf);
1711 			return -1;
1712 		}
1713 
1714 		qos_map_set[count++] = val;
1715 		pos = os_strchr(pos, ',');
1716 		if (!pos)
1717 			break;
1718 		pos++;
1719 	}
1720 
1721 	if (count < 16 || count & 1) {
1722 		wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'",
1723 			   line, buf);
1724 		return -1;
1725 	}
1726 
1727 	os_memcpy(bss->qos_map_set, qos_map_set, count);
1728 	bss->qos_map_set_len = count;
1729 
1730 	return 0;
1731 }
1732 
1733 
1734 #ifdef CONFIG_HS20
hs20_parse_conn_capab(struct hostapd_bss_config * bss,char * buf,int line)1735 static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
1736 				 int line)
1737 {
1738 	u8 *conn_cap;
1739 	char *pos;
1740 
1741 	if (bss->hs20_connection_capability_len >= 0xfff0)
1742 		return -1;
1743 
1744 	conn_cap = os_realloc(bss->hs20_connection_capability,
1745 			      bss->hs20_connection_capability_len + 4);
1746 	if (conn_cap == NULL)
1747 		return -1;
1748 
1749 	bss->hs20_connection_capability = conn_cap;
1750 	conn_cap += bss->hs20_connection_capability_len;
1751 	pos = buf;
1752 	conn_cap[0] = atoi(pos);
1753 	pos = os_strchr(pos, ':');
1754 	if (pos == NULL)
1755 		return -1;
1756 	pos++;
1757 	WPA_PUT_LE16(conn_cap + 1, atoi(pos));
1758 	pos = os_strchr(pos, ':');
1759 	if (pos == NULL)
1760 		return -1;
1761 	pos++;
1762 	conn_cap[3] = atoi(pos);
1763 	bss->hs20_connection_capability_len += 4;
1764 
1765 	return 0;
1766 }
1767 
1768 
hs20_parse_wan_metrics(struct hostapd_bss_config * bss,char * buf,int line)1769 static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf,
1770 				  int line)
1771 {
1772 	u8 *wan_metrics;
1773 	char *pos;
1774 
1775 	/* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */
1776 
1777 	wan_metrics = os_zalloc(13);
1778 	if (wan_metrics == NULL)
1779 		return -1;
1780 
1781 	pos = buf;
1782 	/* WAN Info */
1783 	if (hexstr2bin(pos, wan_metrics, 1) < 0)
1784 		goto fail;
1785 	pos += 2;
1786 	if (*pos != ':')
1787 		goto fail;
1788 	pos++;
1789 
1790 	/* Downlink Speed */
1791 	WPA_PUT_LE32(wan_metrics + 1, atoi(pos));
1792 	pos = os_strchr(pos, ':');
1793 	if (pos == NULL)
1794 		goto fail;
1795 	pos++;
1796 
1797 	/* Uplink Speed */
1798 	WPA_PUT_LE32(wan_metrics + 5, atoi(pos));
1799 	pos = os_strchr(pos, ':');
1800 	if (pos == NULL)
1801 		goto fail;
1802 	pos++;
1803 
1804 	/* Downlink Load */
1805 	wan_metrics[9] = atoi(pos);
1806 	pos = os_strchr(pos, ':');
1807 	if (pos == NULL)
1808 		goto fail;
1809 	pos++;
1810 
1811 	/* Uplink Load */
1812 	wan_metrics[10] = atoi(pos);
1813 	pos = os_strchr(pos, ':');
1814 	if (pos == NULL)
1815 		goto fail;
1816 	pos++;
1817 
1818 	/* LMD */
1819 	WPA_PUT_LE16(wan_metrics + 11, atoi(pos));
1820 
1821 	os_free(bss->hs20_wan_metrics);
1822 	bss->hs20_wan_metrics = wan_metrics;
1823 
1824 	return 0;
1825 
1826 fail:
1827 	wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'",
1828 		   line, buf);
1829 	os_free(wan_metrics);
1830 	return -1;
1831 }
1832 
1833 
hs20_parse_oper_friendly_name(struct hostapd_bss_config * bss,char * pos,int line)1834 static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
1835 					 char *pos, int line)
1836 {
1837 	if (parse_lang_string(&bss->hs20_oper_friendly_name,
1838 			      &bss->hs20_oper_friendly_name_count, pos)) {
1839 		wpa_printf(MSG_ERROR, "Line %d: Invalid "
1840 			   "hs20_oper_friendly_name '%s'", line, pos);
1841 		return -1;
1842 	}
1843 	return 0;
1844 }
1845 
1846 
hs20_parse_icon(struct hostapd_bss_config * bss,char * pos)1847 static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
1848 {
1849 	struct hs20_icon *icon;
1850 	char *end;
1851 
1852 	icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
1853 				sizeof(struct hs20_icon));
1854 	if (icon == NULL)
1855 		return -1;
1856 	bss->hs20_icons = icon;
1857 	icon = &bss->hs20_icons[bss->hs20_icons_count];
1858 	os_memset(icon, 0, sizeof(*icon));
1859 
1860 	icon->width = atoi(pos);
1861 	pos = os_strchr(pos, ':');
1862 	if (pos == NULL)
1863 		return -1;
1864 	pos++;
1865 
1866 	icon->height = atoi(pos);
1867 	pos = os_strchr(pos, ':');
1868 	if (pos == NULL)
1869 		return -1;
1870 	pos++;
1871 
1872 	end = os_strchr(pos, ':');
1873 	if (end == NULL || end - pos > 3)
1874 		return -1;
1875 	os_memcpy(icon->language, pos, end - pos);
1876 	pos = end + 1;
1877 
1878 	end = os_strchr(pos, ':');
1879 	if (end == NULL || end - pos > 255)
1880 		return -1;
1881 	os_memcpy(icon->type, pos, end - pos);
1882 	pos = end + 1;
1883 
1884 	end = os_strchr(pos, ':');
1885 	if (end == NULL || end - pos > 255)
1886 		return -1;
1887 	os_memcpy(icon->name, pos, end - pos);
1888 	pos = end + 1;
1889 
1890 	if (os_strlen(pos) > 255)
1891 		return -1;
1892 	os_memcpy(icon->file, pos, os_strlen(pos));
1893 
1894 	bss->hs20_icons_count++;
1895 
1896 	return 0;
1897 }
1898 
1899 
hs20_parse_osu_ssid(struct hostapd_bss_config * bss,char * pos,int line)1900 static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
1901 			       char *pos, int line)
1902 {
1903 	size_t slen;
1904 	char *str;
1905 
1906 	str = wpa_config_parse_string(pos, &slen);
1907 	if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
1908 		wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, anonymize_ssid(pos));
1909 		os_free(str);
1910 		return -1;
1911 	}
1912 
1913 	os_memcpy(bss->osu_ssid, str, slen);
1914 	bss->osu_ssid_len = slen;
1915 	os_free(str);
1916 
1917 	return 0;
1918 }
1919 
1920 
hs20_parse_osu_server_uri(struct hostapd_bss_config * bss,char * pos,int line)1921 static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
1922 				     char *pos, int line)
1923 {
1924 	struct hs20_osu_provider *p;
1925 
1926 	p = os_realloc_array(bss->hs20_osu_providers,
1927 			     bss->hs20_osu_providers_count + 1, sizeof(*p));
1928 	if (p == NULL)
1929 		return -1;
1930 
1931 	bss->hs20_osu_providers = p;
1932 	bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
1933 	bss->hs20_osu_providers_count++;
1934 	os_memset(bss->last_osu, 0, sizeof(*p));
1935 	bss->last_osu->server_uri = os_strdup(pos);
1936 
1937 	return 0;
1938 }
1939 
1940 
hs20_parse_osu_friendly_name(struct hostapd_bss_config * bss,char * pos,int line)1941 static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
1942 					char *pos, int line)
1943 {
1944 	if (bss->last_osu == NULL) {
1945 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
1946 		return -1;
1947 	}
1948 
1949 	if (parse_lang_string(&bss->last_osu->friendly_name,
1950 			      &bss->last_osu->friendly_name_count, pos)) {
1951 		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
1952 			   line, pos);
1953 		return -1;
1954 	}
1955 
1956 	return 0;
1957 }
1958 
1959 
hs20_parse_osu_nai(struct hostapd_bss_config * bss,char * pos,int line)1960 static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
1961 			      char *pos, int line)
1962 {
1963 	if (bss->last_osu == NULL) {
1964 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
1965 		return -1;
1966 	}
1967 
1968 	os_free(bss->last_osu->osu_nai);
1969 	bss->last_osu->osu_nai = os_strdup(pos);
1970 	if (bss->last_osu->osu_nai == NULL)
1971 		return -1;
1972 
1973 	return 0;
1974 }
1975 
1976 
hs20_parse_osu_nai2(struct hostapd_bss_config * bss,char * pos,int line)1977 static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss,
1978 			       char *pos, int line)
1979 {
1980 	if (bss->last_osu == NULL) {
1981 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
1982 		return -1;
1983 	}
1984 
1985 	os_free(bss->last_osu->osu_nai2);
1986 	bss->last_osu->osu_nai2 = os_strdup(pos);
1987 	if (bss->last_osu->osu_nai2 == NULL)
1988 		return -1;
1989 	bss->hs20_osu_providers_nai_count++;
1990 
1991 	return 0;
1992 }
1993 
1994 
hs20_parse_osu_method_list(struct hostapd_bss_config * bss,char * pos,int line)1995 static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
1996 				      int line)
1997 {
1998 	if (bss->last_osu == NULL) {
1999 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
2000 		return -1;
2001 	}
2002 
2003 	if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
2004 		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
2005 		return -1;
2006 	}
2007 
2008 	return 0;
2009 }
2010 
2011 
hs20_parse_osu_icon(struct hostapd_bss_config * bss,char * pos,int line)2012 static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
2013 			       int line)
2014 {
2015 	char **n;
2016 	struct hs20_osu_provider *p = bss->last_osu;
2017 
2018 	if (p == NULL) {
2019 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
2020 		return -1;
2021 	}
2022 
2023 	n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
2024 	if (n == NULL)
2025 		return -1;
2026 	p->icons = n;
2027 	p->icons[p->icons_count] = os_strdup(pos);
2028 	if (p->icons[p->icons_count] == NULL)
2029 		return -1;
2030 	p->icons_count++;
2031 
2032 	return 0;
2033 }
2034 
2035 
hs20_parse_osu_service_desc(struct hostapd_bss_config * bss,char * pos,int line)2036 static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
2037 				       char *pos, int line)
2038 {
2039 	if (bss->last_osu == NULL) {
2040 		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
2041 		return -1;
2042 	}
2043 
2044 	if (parse_lang_string(&bss->last_osu->service_desc,
2045 			      &bss->last_osu->service_desc_count, pos)) {
2046 		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
2047 			   line, pos);
2048 		return -1;
2049 	}
2050 
2051 	return 0;
2052 }
2053 
2054 
hs20_parse_operator_icon(struct hostapd_bss_config * bss,char * pos,int line)2055 static int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos,
2056 				    int line)
2057 {
2058 	char **n;
2059 
2060 	n = os_realloc_array(bss->hs20_operator_icon,
2061 			     bss->hs20_operator_icon_count + 1, sizeof(char *));
2062 	if (!n)
2063 		return -1;
2064 	bss->hs20_operator_icon = n;
2065 	bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos);
2066 	if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count])
2067 		return -1;
2068 	bss->hs20_operator_icon_count++;
2069 
2070 	return 0;
2071 }
2072 
2073 #endif /* CONFIG_HS20 */
2074 
2075 
2076 #ifdef CONFIG_ACS
hostapd_config_parse_acs_chan_bias(struct hostapd_config * conf,char * pos)2077 static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
2078 					      char *pos)
2079 {
2080 	struct acs_bias *bias = NULL, *tmp;
2081 	unsigned int num = 0;
2082 	char *end;
2083 
2084 	while (*pos) {
2085 		tmp = os_realloc_array(bias, num + 1, sizeof(*bias));
2086 		if (!tmp)
2087 			goto fail;
2088 		bias = tmp;
2089 
2090 		bias[num].channel = atoi(pos);
2091 		if (bias[num].channel <= 0)
2092 			goto fail;
2093 		pos = os_strchr(pos, ':');
2094 		if (!pos)
2095 			goto fail;
2096 		pos++;
2097 		bias[num].bias = strtod(pos, &end);
2098 		if (end == pos || bias[num].bias < 0.0)
2099 			goto fail;
2100 		pos = end;
2101 		if (*pos != ' ' && *pos != '\0')
2102 			goto fail;
2103 		num++;
2104 	}
2105 
2106 	os_free(conf->acs_chan_bias);
2107 	conf->acs_chan_bias = bias;
2108 	conf->num_acs_chan_bias = num;
2109 
2110 	return 0;
2111 fail:
2112 	os_free(bias);
2113 	return -1;
2114 }
2115 #endif /* CONFIG_ACS */
2116 
2117 
parse_wpabuf_hex(int line,const char * name,struct wpabuf ** buf,const char * val)2118 static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf,
2119 			    const char *val)
2120 {
2121 	struct wpabuf *elems;
2122 
2123 	if (val[0] == '\0') {
2124 		wpabuf_free(*buf);
2125 		*buf = NULL;
2126 		return 0;
2127 	}
2128 
2129 	elems = wpabuf_parse_bin(val);
2130 	if (!elems) {
2131 		wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
2132 			   line, name, val);
2133 		return -1;
2134 	}
2135 
2136 	wpabuf_free(*buf);
2137 	*buf = elems;
2138 
2139 	return 0;
2140 }
2141 
2142 
2143 #ifdef CONFIG_FILS
parse_fils_realm(struct hostapd_bss_config * bss,const char * val)2144 static int parse_fils_realm(struct hostapd_bss_config *bss, const char *val)
2145 {
2146 	struct fils_realm *realm;
2147 	size_t len;
2148 
2149 	len = os_strlen(val);
2150 	realm = os_zalloc(sizeof(*realm) + len + 1);
2151 	if (!realm)
2152 		return -1;
2153 
2154 	os_memcpy(realm->realm, val, len);
2155 	if (fils_domain_name_hash(val, realm->hash) < 0) {
2156 		os_free(realm);
2157 		return -1;
2158 	}
2159 	dl_list_add_tail(&bss->fils_realms, &realm->list);
2160 
2161 	return 0;
2162 }
2163 #endif /* CONFIG_FILS */
2164 
2165 
2166 #ifdef EAP_SERVER
parse_tls_flags(const char * val)2167 static unsigned int parse_tls_flags(const char *val)
2168 {
2169 	unsigned int flags = 0;
2170 
2171 	/* Disable TLS v1.3 by default for now to avoid interoperability issue.
2172 	 * This can be enabled by default once the implementation has been fully
2173 	 * completed and tested with other implementations. */
2174 	flags |= TLS_CONN_DISABLE_TLSv1_3;
2175 
2176 	if (os_strstr(val, "[ALLOW-SIGN-RSA-MD5]"))
2177 		flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5;
2178 	if (os_strstr(val, "[DISABLE-TIME-CHECKS]"))
2179 		flags |= TLS_CONN_DISABLE_TIME_CHECKS;
2180 	if (os_strstr(val, "[DISABLE-TLSv1.0]"))
2181 		flags |= TLS_CONN_DISABLE_TLSv1_0;
2182 	if (os_strstr(val, "[ENABLE-TLSv1.0]"))
2183 		flags |= TLS_CONN_ENABLE_TLSv1_0;
2184 	if (os_strstr(val, "[DISABLE-TLSv1.1]"))
2185 		flags |= TLS_CONN_DISABLE_TLSv1_1;
2186 	if (os_strstr(val, "[ENABLE-TLSv1.1]"))
2187 		flags |= TLS_CONN_ENABLE_TLSv1_1;
2188 	if (os_strstr(val, "[DISABLE-TLSv1.2]"))
2189 		flags |= TLS_CONN_DISABLE_TLSv1_2;
2190 	if (os_strstr(val, "[ENABLE-TLSv1.2]"))
2191 		flags |= TLS_CONN_ENABLE_TLSv1_2;
2192 	if (os_strstr(val, "[DISABLE-TLSv1.3]"))
2193 		flags |= TLS_CONN_DISABLE_TLSv1_3;
2194 	if (os_strstr(val, "[ENABLE-TLSv1.3]"))
2195 		flags &= ~TLS_CONN_DISABLE_TLSv1_3;
2196 	if (os_strstr(val, "[SUITEB]"))
2197 		flags |= TLS_CONN_SUITEB;
2198 	if (os_strstr(val, "[SUITEB-NO-ECDH]"))
2199 		flags |= TLS_CONN_SUITEB_NO_ECDH | TLS_CONN_SUITEB;
2200 
2201 	return flags;
2202 }
2203 #endif /* EAP_SERVER */
2204 
2205 
2206 #ifdef CONFIG_AIRTIME_POLICY
add_airtime_weight(struct hostapd_bss_config * bss,char * value)2207 static int add_airtime_weight(struct hostapd_bss_config *bss, char *value)
2208 {
2209 	struct airtime_sta_weight *wt;
2210 	char *pos, *next;
2211 
2212 	wt = os_zalloc(sizeof(*wt));
2213 	if (!wt)
2214 		return -1;
2215 
2216 	/* 02:01:02:03:04:05 10 */
2217 	pos = value;
2218 	next = os_strchr(pos, ' ');
2219 	if (next)
2220 		*next++ = '\0';
2221 	if (!next || hwaddr_aton(pos, wt->addr)) {
2222 		wpa_printf(MSG_ERROR, "Invalid station address: '%s'", anonymize_common(pos));
2223 		os_free(wt);
2224 		return -1;
2225 	}
2226 
2227 	pos = next;
2228 	wt->weight = atoi(pos);
2229 	if (!wt->weight) {
2230 		wpa_printf(MSG_ERROR, "Invalid weight: '%s'", pos);
2231 		os_free(wt);
2232 		return -1;
2233 	}
2234 
2235 	wt->next = bss->airtime_weight_list;
2236 	bss->airtime_weight_list = wt;
2237 	return 0;
2238 }
2239 #endif /* CONFIG_AIRTIME_POLICY */
2240 
2241 
2242 #ifdef CONFIG_SAE
2243 
parse_sae_password(struct hostapd_bss_config * bss,const char * val)2244 static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
2245 {
2246 	struct sae_password_entry *pw;
2247 	const char *pos = val, *pos2, *end = NULL;
2248 
2249 	pw = os_zalloc(sizeof(*pw));
2250 	if (!pw)
2251 		return -1;
2252 	os_memset(pw->peer_addr, 0xff, ETH_ALEN); /* default to wildcard */
2253 
2254 	pos2 = os_strstr(pos, "|mac=");
2255 	if (pos2) {
2256 		end = pos2;
2257 		pos2 += 5;
2258 		if (hwaddr_aton(pos2, pw->peer_addr) < 0)
2259 			goto fail;
2260 		pos = pos2 + ETH_ALEN * 3 - 1;
2261 	}
2262 
2263 	pos2 = os_strstr(pos, "|vlanid=");
2264 	if (pos2) {
2265 		if (!end)
2266 			end = pos2;
2267 		pos2 += 8;
2268 		pw->vlan_id = atoi(pos2);
2269 	}
2270 
2271 #ifdef CONFIG_SAE_PK
2272 	pos2 = os_strstr(pos, "|pk=");
2273 	if (pos2) {
2274 		const char *epos;
2275 		char *tmp;
2276 
2277 		if (!end)
2278 			end = pos2;
2279 		pos2 += 4;
2280 		epos = os_strchr(pos2, '|');
2281 		if (epos) {
2282 			tmp = os_malloc(epos - pos2 + 1);
2283 			if (!tmp)
2284 				goto fail;
2285 			os_memcpy(tmp, pos2, epos - pos2);
2286 			tmp[epos - pos2] = '\0';
2287 		} else {
2288 			tmp = os_strdup(pos2);
2289 			if (!tmp)
2290 				goto fail;
2291 		}
2292 
2293 		pw->pk = sae_parse_pk(tmp);
2294 		str_clear_free(tmp);
2295 		if (!pw->pk)
2296 			goto fail;
2297 	}
2298 #endif /* CONFIG_SAE_PK */
2299 
2300 	pos2 = os_strstr(pos, "|id=");
2301 	if (pos2) {
2302 		if (!end)
2303 			end = pos2;
2304 		pos2 += 4;
2305 		pw->identifier = os_strdup(pos2);
2306 		if (!pw->identifier)
2307 			goto fail;
2308 	}
2309 
2310 	if (!end) {
2311 		pw->password = os_strdup(val);
2312 		if (!pw->password)
2313 			goto fail;
2314 	} else {
2315 		pw->password = os_malloc(end - val + 1);
2316 		if (!pw->password)
2317 			goto fail;
2318 		os_memcpy(pw->password, val, end - val);
2319 		pw->password[end - val] = '\0';
2320 	}
2321 
2322 #ifdef CONFIG_SAE_PK
2323 	if (pw->pk &&
2324 #ifdef CONFIG_TESTING_OPTIONS
2325 	    !bss->sae_pk_password_check_skip &&
2326 #endif /* CONFIG_TESTING_OPTIONS */
2327 	    !sae_pk_valid_password(pw->password)) {
2328 		wpa_printf(MSG_INFO,
2329 			   "Invalid SAE password for a SAE-PK sae_password entry");
2330 		goto fail;
2331 	}
2332 #endif /* CONFIG_SAE_PK */
2333 
2334 	pw->next = bss->sae_passwords;
2335 	bss->sae_passwords = pw;
2336 
2337 	return 0;
2338 fail:
2339 	str_clear_free(pw->password);
2340 	os_free(pw->identifier);
2341 #ifdef CONFIG_SAE_PK
2342 	sae_deinit_pk(pw->pk);
2343 #endif /* CONFIG_SAE_PK */
2344 	os_free(pw);
2345 	return -1;
2346 }
2347 
2348 
parse_sae_password_file(struct hostapd_bss_config * bss,const char * fname)2349 static int parse_sae_password_file(struct hostapd_bss_config *bss,
2350 				   const char *fname)
2351 {
2352 	FILE *f;
2353 	char buf[500], *pos;
2354 	unsigned int line = 0;
2355 
2356 	f = fopen(fname, "r");
2357 	if (!f) {
2358 		wpa_printf(MSG_ERROR, "sae_password_file '%s' not found.",
2359 			   fname);
2360 		return -1;
2361 	}
2362 
2363 	while (fgets(buf, sizeof(buf), f)) {
2364 		pos = os_strchr(buf, '\n');
2365 		if (pos)
2366 			*pos = '\0';
2367 		line++;
2368 		if (parse_sae_password(bss, buf)) {
2369 			wpa_printf(MSG_ERROR,
2370 				   "Invalid SAE password at line %d in '%s'",
2371 				   line, fname);
2372 			fclose(f);
2373 			return -1;
2374 		}
2375 	}
2376 
2377 	fclose(f);
2378 	return 0;
2379 }
2380 
2381 #endif /* CONFIG_SAE */
2382 
2383 
2384 #ifdef CONFIG_DPP2
hostapd_dpp_controller_parse(struct hostapd_bss_config * bss,const char * pos)2385 static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss,
2386 					const char *pos)
2387 {
2388 	struct dpp_controller_conf *conf;
2389 	char *val;
2390 
2391 	conf = os_zalloc(sizeof(*conf));
2392 	if (!conf)
2393 		return -1;
2394 	val = get_param(pos, "ipaddr=");
2395 	if (!val || hostapd_parse_ip_addr(val, &conf->ipaddr))
2396 		goto fail;
2397 	os_free(val);
2398 	val = get_param(pos, "pkhash=");
2399 	if (!val || os_strlen(val) != 2 * SHA256_MAC_LEN ||
2400 	    hexstr2bin(val, conf->pkhash, SHA256_MAC_LEN) < 0)
2401 		goto fail;
2402 	os_free(val);
2403 	conf->next = bss->dpp_controller;
2404 	bss->dpp_controller = conf;
2405 	return 0;
2406 fail:
2407 	os_free(val);
2408 	os_free(conf);
2409 	return -1;
2410 }
2411 #endif /* CONFIG_DPP2 */
2412 
2413 
get_hex_config(u8 * buf,size_t max_len,int line,const char * field,const char * val)2414 static int get_hex_config(u8 *buf, size_t max_len, int line,
2415 			  const char *field, const char *val)
2416 {
2417 	size_t hlen = os_strlen(val), len = hlen / 2;
2418 	u8 tmp[EXT_CAPA_MAX_LEN];
2419 
2420 	os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
2421 	if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
2422 		wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
2423 		return -1;
2424 	}
2425 	os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
2426 	return 0;
2427 }
2428 
hostapd_config_bw_auto_adaptation(struct hostapd_config * conf)2429 static void hostapd_config_bw_auto_adaptation(struct hostapd_config *conf)
2430 {
2431 	wpa_printf(MSG_INFO, "ap mode:%d, channel:%d, ieee80211n:%d,ht_capab:%d, sec_ch:%d, ht20_set_flag:%d",
2432 		conf->hw_mode, conf->channel, conf->ieee80211n,
2433 		conf->ht_capab, conf->secondary_channel, conf->ht20_set_flag);
2434 	wpa_printf(MSG_INFO, "ieee80211ac:%d,vht_capab:%d,require_vht:%d,chwidth:%d,freq_seg0_idx:%d,freq_seg1_idx:%d",
2435 		conf->ieee80211ac, conf->vht_capab, conf->require_vht, conf->vht_oper_chwidth,
2436 		conf->vht_oper_centr_freq_seg0_idx, conf->vht_oper_centr_freq_seg1_idx);
2437 
2438 #ifdef CONFIG_IEEE80211AC
2439 	if (!conf->ieee80211ac && HOSTAPD_MODE_IEEE80211A == conf->hw_mode) {
2440 		if (((conf->channel <= 161 && conf->channel >= 149) || (conf->channel >= 36 && conf->channel <= 48)) &&
2441 			!conf->ht20_set_flag) {
2442 			wpa_printf(MSG_INFO, "soft ap, 5G mode, try use 11ac VHT80");
2443 			switch (conf->channel) {
2444 				case 36:
2445 				case 44:
2446 					conf->secondary_channel = 1;
2447 				#ifdef CONFIG_OPEN_HARMONY_PATCH
2448 					if (conf->bandwidth == AP_BANDWIDTH_160M) {
2449 						conf->vht_oper_centr_freq_seg0_idx = 50;
2450 						conf->vht_capab |= VHT_CAP_SHORT_GI_160;
2451 						conf->vht_oper_chwidth = CHANWIDTH_160MHZ;
2452 					} else {
2453 						conf->vht_oper_centr_freq_seg0_idx = 42;
2454 						conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
2455 						conf->vht_capab |= VHT_CAP_SHORT_GI_80;
2456 					}
2457 				#else
2458 					conf->vht_oper_centr_freq_seg0_idx = 42;
2459 					conf->vht_capab |= VHT_CAP_SHORT_GI_80;
2460 					conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
2461 				#endif
2462 					break;
2463 				case 40:
2464 				case 48:
2465 					conf->secondary_channel = -1;
2466 				#ifdef CONFIG_OPEN_HARMONY_PATCH
2467 					if (conf->bandwidth == AP_BANDWIDTH_160M) {
2468 						conf->vht_oper_centr_freq_seg0_idx = 50;
2469 						conf->vht_capab |= VHT_CAP_SHORT_GI_160;
2470 						conf->vht_oper_chwidth = CHANWIDTH_160MHZ;
2471 					} else {
2472 						conf->vht_oper_centr_freq_seg0_idx = 42;
2473 						conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
2474 						conf->vht_capab |= VHT_CAP_SHORT_GI_80;
2475 					}
2476 				#else
2477 					conf->vht_oper_centr_freq_seg0_idx = 42;
2478 					conf->vht_capab |= VHT_CAP_SHORT_GI_80;
2479 					conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
2480 				#endif
2481 					break;
2482 				case 149:
2483 				case 157:
2484 					conf->secondary_channel = 1;
2485 					conf->vht_oper_centr_freq_seg0_idx = 155;
2486 					conf->vht_capab |= VHT_CAP_SHORT_GI_80;
2487 					conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
2488 					break;
2489 				case 153:
2490 				case 161:
2491 					conf->secondary_channel = -1;
2492 					conf->vht_oper_centr_freq_seg0_idx = 155;
2493 					conf->vht_capab |= VHT_CAP_SHORT_GI_80;
2494 					conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
2495 					break;
2496 				default:
2497 					break;
2498 			}
2499 
2500 			conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
2501 		}
2502 
2503 		conf->ieee80211ac = 1;
2504 		wpa_printf(MSG_INFO, "Set default_mode(11ac) in 5G ieee80211ac:%d,vht_capab:%d,chwidth:%d,sec_ch:%d",
2505 			conf->ieee80211ac, conf->vht_capab, conf->vht_oper_chwidth, conf->secondary_channel);
2506 	}
2507 #endif /* CONFIG_IEEE80211AC */
2508 }
2509 #ifdef CONFIG_IEEE80211BE
get_u16(const char * pos,int line,u16 * ret_val)2510 static int get_u16(const char *pos, int line, u16 *ret_val)
2511 {
2512 	char *end;
2513 	long int val = strtol(pos, &end, 0);
2514 
2515 	if (*end || val < 0 || val > 0xffff) {
2516 		wpa_printf(MSG_ERROR, "Line %d: Invalid value '%s'",
2517 			   line, pos);
2518 		return -1;
2519 	}
2520 
2521 	*ret_val = val;
2522 	return 0;
2523 }
2524 #endif /* CONFIG_IEEE80211BE */
2525 
2526 
hostapd_config_fill(struct hostapd_config * conf,struct hostapd_bss_config * bss,const char * buf,char * pos,int line)2527 static int hostapd_config_fill(struct hostapd_config *conf,
2528 			       struct hostapd_bss_config *bss,
2529 			       const char *buf, char *pos, int line)
2530 {
2531 	if (os_strcmp(buf, "interface") == 0) {
2532 		os_strlcpy(conf->bss[0]->iface, pos,
2533 			   sizeof(conf->bss[0]->iface));
2534 	} else if (os_strcmp(buf, "bridge") == 0) {
2535 		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
2536 	} else if (os_strcmp(buf, "bridge_hairpin") == 0) {
2537 		bss->bridge_hairpin = atoi(pos);
2538 	} else if (os_strcmp(buf, "vlan_bridge") == 0) {
2539 		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
2540 	} else if (os_strcmp(buf, "wds_bridge") == 0) {
2541 		os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
2542 	} else if (os_strcmp(buf, "driver") == 0) {
2543 		int j;
2544 		const struct wpa_driver_ops *driver = NULL;
2545 
2546 		for (j = 0; wpa_drivers[j]; j++) {
2547 			if (os_strcmp(pos, wpa_drivers[j]->name) == 0) {
2548 				driver = wpa_drivers[j];
2549 				break;
2550 			}
2551 		}
2552 		if (!driver) {
2553 			wpa_printf(MSG_ERROR,
2554 				   "Line %d: invalid/unknown driver '%s'",
2555 				   line, pos);
2556 			return 1;
2557 		}
2558 		conf->driver = driver;
2559 	} else if (os_strcmp(buf, "driver_params") == 0) {
2560 		os_free(conf->driver_params);
2561 		conf->driver_params = os_strdup(pos);
2562 	} else if (os_strcmp(buf, "debug") == 0) {
2563 		wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore",
2564 			   line);
2565 	} else if (os_strcmp(buf, "logger_syslog_level") == 0) {
2566 		bss->logger_syslog_level = atoi(pos);
2567 	} else if (os_strcmp(buf, "logger_stdout_level") == 0) {
2568 		bss->logger_stdout_level = atoi(pos);
2569 	} else if (os_strcmp(buf, "logger_syslog") == 0) {
2570 		bss->logger_syslog = atoi(pos);
2571 	} else if (os_strcmp(buf, "logger_stdout") == 0) {
2572 		bss->logger_stdout = atoi(pos);
2573 	} else if (os_strcmp(buf, "dump_file") == 0) {
2574 		wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
2575 			   line);
2576 	} else if (os_strcmp(buf, "ssid") == 0) {
2577 		struct hostapd_ssid *ssid = &bss->ssid;
2578 
2579 		ssid->ssid_len = os_strlen(pos);
2580 		if (ssid->ssid_len > SSID_MAX_LEN || ssid->ssid_len < 1) {
2581 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
2582 				   line, anonymize_ssid(pos));
2583 			return 1;
2584 		}
2585 		os_memcpy(ssid->ssid, pos, ssid->ssid_len);
2586 		ssid->ssid_set = 1;
2587 		ssid->short_ssid = ieee80211_crc32(ssid->ssid, ssid->ssid_len);
2588 	} else if (os_strcmp(buf, "ssid2") == 0) {
2589 		struct hostapd_ssid *ssid = &bss->ssid;
2590 		size_t slen;
2591 		char *str = wpa_config_parse_string(pos, &slen);
2592 		if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
2593 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
2594 				   line, anonymize_ssid(pos));
2595 			os_free(str);
2596 			return 1;
2597 		}
2598 		os_memcpy(ssid->ssid, str, slen);
2599 		ssid->ssid_len = slen;
2600 		ssid->ssid_set = 1;
2601 		ssid->short_ssid = ieee80211_crc32(ssid->ssid, ssid->ssid_len);
2602 		os_free(str);
2603 	} else if (os_strcmp(buf, "utf8_ssid") == 0) {
2604 		bss->ssid.utf8_ssid = atoi(pos) > 0;
2605 	} else if (os_strcmp(buf, "macaddr_acl") == 0) {
2606 		enum macaddr_acl acl = atoi(pos);
2607 
2608 		if (acl != ACCEPT_UNLESS_DENIED &&
2609 		    acl != DENY_UNLESS_ACCEPTED &&
2610 		    acl != USE_EXTERNAL_RADIUS_AUTH) {
2611 			wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d",
2612 				   line, acl);
2613 			return 1;
2614 		}
2615 		bss->macaddr_acl = acl;
2616 	} else if (os_strcmp(buf, "accept_mac_file") == 0) {
2617 		if (hostapd_config_read_maclist(pos, &bss->accept_mac,
2618 						&bss->num_accept_mac)) {
2619 			wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'",
2620 				   line, pos);
2621 			return 1;
2622 		}
2623 	} else if (os_strcmp(buf, "deny_mac_file") == 0) {
2624 		if (hostapd_config_read_maclist(pos, &bss->deny_mac,
2625 						&bss->num_deny_mac)) {
2626 			wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'",
2627 				   line, pos);
2628 			return 1;
2629 		}
2630 	} else if (os_strcmp(buf, "wds_sta") == 0) {
2631 		bss->wds_sta = atoi(pos);
2632 	} else if (os_strcmp(buf, "start_disabled") == 0) {
2633 		bss->start_disabled = atoi(pos);
2634 	} else if (os_strcmp(buf, "ap_isolate") == 0) {
2635 		bss->isolate = atoi(pos);
2636 	} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
2637 		bss->ap_max_inactivity = atoi(pos);
2638 	} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
2639 		bss->skip_inactivity_poll = atoi(pos);
2640 	} else if (os_strcmp(buf, "bss_max_idle") == 0) {
2641 		int val = atoi(pos);
2642 
2643 		if (val < 0 || val > 2) {
2644 			wpa_printf(MSG_ERROR,
2645 				   "Line %d: Invalid bss_max_idle value", line);
2646 			return 1;
2647 		}
2648 		bss->bss_max_idle = val;
2649 	} else if (os_strcmp(buf, "max_acceptable_idle_period") == 0) {
2650 		bss->max_acceptable_idle_period = atoi(pos);
2651 	} else if (os_strcmp(buf, "no_disconnect_on_group_keyerror") == 0) {
2652 		int val = atoi(pos);
2653 
2654 		if (val < 0 || val > 1) {
2655 			wpa_printf(MSG_ERROR,
2656 				   "Line %d: Invalid no_disconnect_on_group_keyerror",
2657 				   line);
2658 			return 1;
2659 		}
2660 		bss->no_disconnect_on_group_keyerror = val;
2661 	} else if (os_strcmp(buf, "config_id") == 0) {
2662 		os_free(bss->config_id);
2663 		bss->config_id = os_strdup(pos);
2664 	} else if (os_strcmp(buf, "country_code") == 0) {
2665 		if (pos[0] < 'A' || pos[0] > 'Z' ||
2666 		    pos[1] < 'A' || pos[1] > 'Z') {
2667 			wpa_printf(MSG_ERROR,
2668 				   "Line %d: Invalid country_code '%s'",
2669 				   line, pos);
2670 			return 1;
2671 		}
2672 		os_memcpy(conf->country, pos, 2);
2673 	} else if (os_strcmp(buf, "country3") == 0) {
2674 		conf->country[2] = strtol(pos, NULL, 16);
2675 	} else if (os_strcmp(buf, "ieee80211d") == 0) {
2676 		conf->ieee80211d = atoi(pos);
2677 	} else if (os_strcmp(buf, "ieee80211h") == 0) {
2678 		conf->ieee80211h = atoi(pos);
2679 	} else if (os_strcmp(buf, "ieee8021x") == 0) {
2680 		bss->ieee802_1x = atoi(pos);
2681 	} else if (os_strcmp(buf, "eapol_version") == 0) {
2682 		int eapol_version = atoi(pos);
2683 #ifdef CONFIG_MACSEC
2684 		int max_ver = 3;
2685 #else /* CONFIG_MACSEC */
2686 		int max_ver = 2;
2687 #endif /* CONFIG_MACSEC */
2688 
2689 		if (eapol_version < 1 || eapol_version > max_ver) {
2690 			wpa_printf(MSG_ERROR,
2691 				   "Line %d: invalid EAPOL version (%d): '%s'.",
2692 				   line, eapol_version, pos);
2693 			return 1;
2694 		}
2695 		bss->eapol_version = eapol_version;
2696 		wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version);
2697 #ifdef EAP_SERVER
2698 	} else if (os_strcmp(buf, "eap_authenticator") == 0) {
2699 		bss->eap_server = atoi(pos);
2700 		wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line);
2701 	} else if (os_strcmp(buf, "eap_server") == 0) {
2702 		bss->eap_server = atoi(pos);
2703 	} else if (os_strcmp(buf, "eap_user_file") == 0) {
2704 		if (hostapd_config_read_eap_user(pos, bss))
2705 			return 1;
2706 	} else if (os_strcmp(buf, "ca_cert") == 0) {
2707 		os_free(bss->ca_cert);
2708 		bss->ca_cert = os_strdup(pos);
2709 	} else if (os_strcmp(buf, "server_cert") == 0) {
2710 		os_free(bss->server_cert);
2711 		bss->server_cert = os_strdup(pos);
2712 	} else if (os_strcmp(buf, "server_cert2") == 0) {
2713 		os_free(bss->server_cert2);
2714 		bss->server_cert2 = os_strdup(pos);
2715 	} else if (os_strcmp(buf, "private_key") == 0) {
2716 		os_free(bss->private_key);
2717 		bss->private_key = os_strdup(pos);
2718 	} else if (os_strcmp(buf, "private_key2") == 0) {
2719 		os_free(bss->private_key2);
2720 		bss->private_key2 = os_strdup(pos);
2721 	} else if (os_strcmp(buf, "private_key_passwd") == 0) {
2722 		os_free(bss->private_key_passwd);
2723 		bss->private_key_passwd = os_strdup(pos);
2724 	} else if (os_strcmp(buf, "private_key_passwd2") == 0) {
2725 		os_free(bss->private_key_passwd2);
2726 		bss->private_key_passwd2 = os_strdup(pos);
2727 	} else if (os_strcmp(buf, "check_cert_subject") == 0) {
2728 		if (!pos[0]) {
2729 			wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'",
2730 				   line, pos);
2731 			return 1;
2732 		}
2733 		os_free(bss->check_cert_subject);
2734 		bss->check_cert_subject = os_strdup(pos);
2735 		if (!bss->check_cert_subject)
2736 			return 1;
2737 	} else if (os_strcmp(buf, "check_crl") == 0) {
2738 		bss->check_crl = atoi(pos);
2739 	} else if (os_strcmp(buf, "check_crl_strict") == 0) {
2740 		bss->check_crl_strict = atoi(pos);
2741 	} else if (os_strcmp(buf, "crl_reload_interval") == 0) {
2742 		bss->crl_reload_interval = atoi(pos);
2743 	} else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
2744 		bss->tls_session_lifetime = atoi(pos);
2745 	} else if (os_strcmp(buf, "tls_flags") == 0) {
2746 		bss->tls_flags = parse_tls_flags(pos);
2747 	} else if (os_strcmp(buf, "max_auth_rounds") == 0) {
2748 		bss->max_auth_rounds = atoi(pos);
2749 	} else if (os_strcmp(buf, "max_auth_rounds_short") == 0) {
2750 		bss->max_auth_rounds_short = atoi(pos);
2751 	} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
2752 		os_free(bss->ocsp_stapling_response);
2753 		bss->ocsp_stapling_response = os_strdup(pos);
2754 	} else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) {
2755 		os_free(bss->ocsp_stapling_response_multi);
2756 		bss->ocsp_stapling_response_multi = os_strdup(pos);
2757 	} else if (os_strcmp(buf, "dh_file") == 0) {
2758 		os_free(bss->dh_file);
2759 		bss->dh_file = os_strdup(pos);
2760 	} else if (os_strcmp(buf, "openssl_ciphers") == 0) {
2761 		os_free(bss->openssl_ciphers);
2762 		bss->openssl_ciphers = os_strdup(pos);
2763 	} else if (os_strcmp(buf, "openssl_ecdh_curves") == 0) {
2764 		os_free(bss->openssl_ecdh_curves);
2765 		bss->openssl_ecdh_curves = os_strdup(pos);
2766 	} else if (os_strcmp(buf, "fragment_size") == 0) {
2767 		bss->fragment_size = atoi(pos);
2768 #ifdef EAP_SERVER_FAST
2769 	} else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
2770 		os_free(bss->pac_opaque_encr_key);
2771 		bss->pac_opaque_encr_key = os_malloc(16);
2772 		if (bss->pac_opaque_encr_key == NULL) {
2773 			wpa_printf(MSG_ERROR,
2774 				   "Line %d: No memory for pac_opaque_encr_key",
2775 				   line);
2776 			return 1;
2777 		} else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) {
2778 			wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key",
2779 				   line);
2780 			return 1;
2781 		}
2782 	} else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
2783 		size_t idlen = os_strlen(pos);
2784 		if (idlen & 1) {
2785 			wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id",
2786 				   line);
2787 			return 1;
2788 		}
2789 		os_free(bss->eap_fast_a_id);
2790 		bss->eap_fast_a_id = os_malloc(idlen / 2);
2791 		if (bss->eap_fast_a_id == NULL ||
2792 		    hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) {
2793 			wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id",
2794 				   line);
2795 			os_free(bss->eap_fast_a_id);
2796 			bss->eap_fast_a_id = NULL;
2797 			return 1;
2798 		} else {
2799 			bss->eap_fast_a_id_len = idlen / 2;
2800 		}
2801 	} else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
2802 		os_free(bss->eap_fast_a_id_info);
2803 		bss->eap_fast_a_id_info = os_strdup(pos);
2804 	} else if (os_strcmp(buf, "eap_fast_prov") == 0) {
2805 		bss->eap_fast_prov = atoi(pos);
2806 	} else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
2807 		bss->pac_key_lifetime = atoi(pos);
2808 	} else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
2809 		bss->pac_key_refresh_time = atoi(pos);
2810 #endif /* EAP_SERVER_FAST */
2811 #ifdef EAP_SERVER_TEAP
2812 	} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
2813 		int val = atoi(pos);
2814 
2815 		if (val < 0 || val > 2) {
2816 			wpa_printf(MSG_ERROR,
2817 				   "Line %d: Invalid eap_teap_auth value",
2818 				   line);
2819 			return 1;
2820 		}
2821 		bss->eap_teap_auth = val;
2822 	} else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) {
2823 		bss->eap_teap_pac_no_inner = atoi(pos);
2824 	} else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
2825 		bss->eap_teap_separate_result = atoi(pos);
2826 	} else if (os_strcmp(buf, "eap_teap_id") == 0) {
2827 		bss->eap_teap_id = atoi(pos);
2828 	} else if (os_strcmp(buf, "eap_teap_method_sequence") == 0) {
2829 		bss->eap_teap_method_sequence = atoi(pos);
2830 #endif /* EAP_SERVER_TEAP */
2831 #ifdef EAP_SERVER_SIM
2832 	} else if (os_strcmp(buf, "eap_sim_db") == 0) {
2833 		os_free(bss->eap_sim_db);
2834 		bss->eap_sim_db = os_strdup(pos);
2835 	} else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) {
2836 		bss->eap_sim_db_timeout = atoi(pos);
2837 	} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
2838 		bss->eap_sim_aka_result_ind = atoi(pos);
2839 	} else if (os_strcmp(buf, "eap_sim_id") == 0) {
2840 		bss->eap_sim_id = atoi(pos);
2841 	} else if (os_strcmp(buf, "imsi_privacy_key") == 0) {
2842 		os_free(bss->imsi_privacy_key);
2843 		bss->imsi_privacy_key = os_strdup(pos);
2844 	} else if (os_strcmp(buf, "eap_sim_aka_fast_reauth_limit") == 0) {
2845 		bss->eap_sim_aka_fast_reauth_limit = atoi(pos);
2846 #endif /* EAP_SERVER_SIM */
2847 #ifdef EAP_SERVER_TNC
2848 	} else if (os_strcmp(buf, "tnc") == 0) {
2849 		bss->tnc = atoi(pos);
2850 #endif /* EAP_SERVER_TNC */
2851 #ifdef EAP_SERVER_PWD
2852 	} else if (os_strcmp(buf, "pwd_group") == 0) {
2853 		bss->pwd_group = atoi(pos);
2854 #endif /* EAP_SERVER_PWD */
2855 #ifdef CONFIG_ERP
2856 	} else if (os_strcmp(buf, "eap_server_erp") == 0) {
2857 		bss->eap_server_erp = atoi(pos);
2858 #endif /* CONFIG_ERP */
2859 #endif /* EAP_SERVER */
2860 	} else if (os_strcmp(buf, "eap_message") == 0) {
2861 		char *term;
2862 		os_free(bss->eap_req_id_text);
2863 		bss->eap_req_id_text = os_strdup(pos);
2864 		if (bss->eap_req_id_text == NULL) {
2865 			wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text",
2866 				   line);
2867 			return 1;
2868 		}
2869 		bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text);
2870 		term = os_strstr(bss->eap_req_id_text, "\\0");
2871 		if (term) {
2872 			*term++ = '\0';
2873 			os_memmove(term, term + 1,
2874 				   bss->eap_req_id_text_len -
2875 				   (term - bss->eap_req_id_text) - 1);
2876 			bss->eap_req_id_text_len--;
2877 		}
2878 	} else if (os_strcmp(buf, "erp_send_reauth_start") == 0) {
2879 		bss->erp_send_reauth_start = atoi(pos);
2880 	} else if (os_strcmp(buf, "erp_domain") == 0) {
2881 		os_free(bss->erp_domain);
2882 		bss->erp_domain = os_strdup(pos);
2883 #ifdef CONFIG_WEP
2884 	} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
2885 		int val = atoi(pos);
2886 
2887 		if (val < 0 || val > 13) {
2888 			wpa_printf(MSG_ERROR,
2889 				   "Line %d: invalid WEP key len %d (= %d bits)",
2890 				   line, val, val * 8);
2891 			return 1;
2892 		}
2893 		bss->default_wep_key_len = val;
2894 	} else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
2895 		int val = atoi(pos);
2896 
2897 		if (val < 0 || val > 13) {
2898 			wpa_printf(MSG_ERROR,
2899 				   "Line %d: invalid WEP key len %d (= %d bits)",
2900 				   line, val, val * 8);
2901 			return 1;
2902 		}
2903 		bss->individual_wep_key_len = val;
2904 	} else if (os_strcmp(buf, "wep_rekey_period") == 0) {
2905 		bss->wep_rekeying_period = atoi(pos);
2906 		if (bss->wep_rekeying_period < 0) {
2907 			wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
2908 				   line, bss->wep_rekeying_period);
2909 			return 1;
2910 		}
2911 #endif /* CONFIG_WEP */
2912 	} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
2913 		bss->eap_reauth_period = atoi(pos);
2914 		if (bss->eap_reauth_period < 0) {
2915 			wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
2916 				   line, bss->eap_reauth_period);
2917 			return 1;
2918 		}
2919 	} else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
2920 		bss->eapol_key_index_workaround = atoi(pos);
2921 #ifdef CONFIG_IAPP
2922 	} else if (os_strcmp(buf, "iapp_interface") == 0) {
2923 		wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
2924 #endif /* CONFIG_IAPP */
2925 	} else if (os_strcmp(buf, "own_ip_addr") == 0) {
2926 		if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
2927 			wpa_printf(MSG_ERROR,
2928 				   "Line %d: invalid IP address '%s'",
2929 				   line, pos);
2930 			return 1;
2931 		}
2932 	} else if (os_strcmp(buf, "nas_identifier") == 0) {
2933 		os_free(bss->nas_identifier);
2934 		bss->nas_identifier = os_strdup(pos);
2935 #ifndef CONFIG_NO_RADIUS
2936 	} else if (os_strcmp(buf, "radius_client_addr") == 0) {
2937 		if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) {
2938 			wpa_printf(MSG_ERROR,
2939 				   "Line %d: invalid IP address '%s'",
2940 				   line, pos);
2941 			return 1;
2942 		}
2943 		bss->radius->force_client_addr = 1;
2944 	} else if (os_strcmp(buf, "radius_client_dev") == 0) {
2945 			os_free(bss->radius->force_client_dev);
2946 			bss->radius->force_client_dev = os_strdup(pos);
2947 	} else if (os_strcmp(buf, "auth_server_addr") == 0) {
2948 		if (hostapd_config_read_radius_addr(
2949 			    &bss->radius->auth_servers,
2950 			    &bss->radius->num_auth_servers, pos, 1812,
2951 			    &bss->radius->auth_server)) {
2952 			wpa_printf(MSG_ERROR,
2953 				   "Line %d: invalid IP address '%s'",
2954 				   line, pos);
2955 			return 1;
2956 		}
2957 	} else if (bss->radius->auth_server &&
2958 		   os_strcmp(buf, "auth_server_addr_replace") == 0) {
2959 		if (hostapd_parse_ip_addr(pos,
2960 					  &bss->radius->auth_server->addr)) {
2961 			wpa_printf(MSG_ERROR,
2962 				   "Line %d: invalid IP address '%s'",
2963 				   line, pos);
2964 			return 1;
2965 		}
2966 	} else if (bss->radius->auth_server &&
2967 		   os_strcmp(buf, "auth_server_port") == 0) {
2968 		bss->radius->auth_server->port = atoi(pos);
2969 	} else if (bss->radius->auth_server &&
2970 		   os_strcmp(buf, "auth_server_shared_secret") == 0) {
2971 		int len = os_strlen(pos);
2972 		if (len == 0) {
2973 			/* RFC 2865, Ch. 3 */
2974 			wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
2975 				   line);
2976 			return 1;
2977 		}
2978 		os_free(bss->radius->auth_server->shared_secret);
2979 		bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
2980 		bss->radius->auth_server->shared_secret_len = len;
2981 	} else if (bss->radius->auth_server &&
2982 		   os_strcmp(buf, "auth_server_type") == 0) {
2983 		if (os_strcmp(pos, "UDP") == 0) {
2984 			bss->radius->auth_server->tls = false;
2985 #ifdef CONFIG_RADIUS_TLS
2986 		} else if (os_strcmp(pos, "TLS") == 0) {
2987 			bss->radius->auth_server->tls = true;
2988 #endif /* CONFIG_RADIUS_TLS */
2989 		} else {
2990 			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
2991 				   line, pos);
2992 			return 1;
2993 		}
2994 #ifdef CONFIG_RADIUS_TLS
2995 	} else if (bss->radius->auth_server &&
2996 		   os_strcmp(buf, "auth_server_ca_cert") == 0) {
2997 		os_free(bss->radius->auth_server->ca_cert);
2998 		bss->radius->auth_server->ca_cert = os_strdup(pos);
2999 	} else if (bss->radius->auth_server &&
3000 		   os_strcmp(buf, "auth_server_client_cert") == 0) {
3001 		os_free(bss->radius->auth_server->client_cert);
3002 		bss->radius->auth_server->client_cert = os_strdup(pos);
3003 	} else if (bss->radius->auth_server &&
3004 		   os_strcmp(buf, "auth_server_private_key") == 0) {
3005 		os_free(bss->radius->auth_server->private_key);
3006 		bss->radius->auth_server->private_key = os_strdup(pos);
3007 	} else if (bss->radius->auth_server &&
3008 		   os_strcmp(buf, "auth_server_private_key_passwd") == 0) {
3009 		os_free(bss->radius->auth_server->private_key_passwd);
3010 		bss->radius->auth_server->private_key_passwd = os_strdup(pos);
3011 #endif /* CONFIG_RADIUS_TLS */
3012 	} else if (os_strcmp(buf, "acct_server_addr") == 0) {
3013 		if (hostapd_config_read_radius_addr(
3014 			    &bss->radius->acct_servers,
3015 			    &bss->radius->num_acct_servers, pos, 1813,
3016 			    &bss->radius->acct_server)) {
3017 			wpa_printf(MSG_ERROR,
3018 				   "Line %d: invalid IP address '%s'",
3019 				   line, pos);
3020 			return 1;
3021 		}
3022 	} else if (bss->radius->acct_server &&
3023 		   os_strcmp(buf, "acct_server_addr_replace") == 0) {
3024 		if (hostapd_parse_ip_addr(pos,
3025 					  &bss->radius->acct_server->addr)) {
3026 			wpa_printf(MSG_ERROR,
3027 				   "Line %d: invalid IP address '%s'",
3028 				   line, pos);
3029 			return 1;
3030 		}
3031 	} else if (bss->radius->acct_server &&
3032 		   os_strcmp(buf, "acct_server_port") == 0) {
3033 		bss->radius->acct_server->port = atoi(pos);
3034 	} else if (bss->radius->acct_server &&
3035 		   os_strcmp(buf, "acct_server_shared_secret") == 0) {
3036 		int len = os_strlen(pos);
3037 		if (len == 0) {
3038 			/* RFC 2865, Ch. 3 */
3039 			wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
3040 				   line);
3041 			return 1;
3042 		}
3043 		os_free(bss->radius->acct_server->shared_secret);
3044 		bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
3045 		bss->radius->acct_server->shared_secret_len = len;
3046 	} else if (bss->radius->acct_server &&
3047 		   os_strcmp(buf, "acct_server_type") == 0) {
3048 		if (os_strcmp(pos, "UDP") == 0) {
3049 			bss->radius->acct_server->tls = false;
3050 #ifdef CONFIG_RADIUS_TLS
3051 		} else if (os_strcmp(pos, "TLS") == 0) {
3052 			bss->radius->acct_server->tls = true;
3053 #endif /* CONFIG_RADIUS_TLS */
3054 		} else {
3055 			wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
3056 				   line, pos);
3057 			return 1;
3058 		}
3059 #ifdef CONFIG_RADIUS_TLS
3060 	} else if (bss->radius->acct_server &&
3061 		   os_strcmp(buf, "acct_server_ca_cert") == 0) {
3062 		os_free(bss->radius->acct_server->ca_cert);
3063 		bss->radius->acct_server->ca_cert = os_strdup(pos);
3064 	} else if (bss->radius->acct_server &&
3065 		   os_strcmp(buf, "acct_server_client_cert") == 0) {
3066 		os_free(bss->radius->acct_server->client_cert);
3067 		bss->radius->acct_server->client_cert = os_strdup(pos);
3068 	} else if (bss->radius->acct_server &&
3069 		   os_strcmp(buf, "acct_server_private_key") == 0) {
3070 		os_free(bss->radius->acct_server->private_key);
3071 		bss->radius->acct_server->private_key = os_strdup(pos);
3072 	} else if (bss->radius->acct_server &&
3073 		   os_strcmp(buf, "acct_server_private_key_passwd") == 0) {
3074 		os_free(bss->radius->acct_server->private_key_passwd);
3075 		bss->radius->acct_server->private_key_passwd = os_strdup(pos);
3076 #endif /* CONFIG_RADIUS_TLS */
3077 	} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
3078 		bss->radius->retry_primary_interval = atoi(pos);
3079 	} else if (os_strcmp(buf,
3080 			     "radius_require_message_authenticator") == 0) {
3081 		bss->radius_require_message_authenticator = atoi(pos);
3082 	} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
3083 		bss->acct_interim_interval = atoi(pos);
3084 	} else if (os_strcmp(buf, "radius_request_cui") == 0) {
3085 		bss->radius_request_cui = atoi(pos);
3086 	} else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
3087 		struct hostapd_radius_attr *attr, *a;
3088 		attr = hostapd_parse_radius_attr(pos);
3089 		if (attr == NULL) {
3090 			wpa_printf(MSG_ERROR,
3091 				   "Line %d: invalid radius_auth_req_attr",
3092 				   line);
3093 			return 1;
3094 		} else if (bss->radius_auth_req_attr == NULL) {
3095 			bss->radius_auth_req_attr = attr;
3096 		} else {
3097 			a = bss->radius_auth_req_attr;
3098 			while (a->next)
3099 				a = a->next;
3100 			a->next = attr;
3101 		}
3102 	} else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
3103 		struct hostapd_radius_attr *attr, *a;
3104 		attr = hostapd_parse_radius_attr(pos);
3105 		if (attr == NULL) {
3106 			wpa_printf(MSG_ERROR,
3107 				   "Line %d: invalid radius_acct_req_attr",
3108 				   line);
3109 			return 1;
3110 		} else if (bss->radius_acct_req_attr == NULL) {
3111 			bss->radius_acct_req_attr = attr;
3112 		} else {
3113 			a = bss->radius_acct_req_attr;
3114 			while (a->next)
3115 				a = a->next;
3116 			a->next = attr;
3117 		}
3118 	} else if (os_strcmp(buf, "radius_req_attr_sqlite") == 0) {
3119 		os_free(bss->radius_req_attr_sqlite);
3120 		bss->radius_req_attr_sqlite = os_strdup(pos);
3121 	} else if (os_strcmp(buf, "radius_das_port") == 0) {
3122 		bss->radius_das_port = atoi(pos);
3123 	} else if (os_strcmp(buf, "radius_das_client") == 0) {
3124 		if (hostapd_parse_das_client(bss, pos) < 0) {
3125 			wpa_printf(MSG_ERROR, "Line %d: invalid DAS client",
3126 				   line);
3127 			return 1;
3128 		}
3129 	} else if (os_strcmp(buf, "radius_das_time_window") == 0) {
3130 		bss->radius_das_time_window = atoi(pos);
3131 	} else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
3132 		bss->radius_das_require_event_timestamp = atoi(pos);
3133 	} else if (os_strcmp(buf, "radius_das_require_message_authenticator") ==
3134 		   0) {
3135 		bss->radius_das_require_message_authenticator = atoi(pos);
3136 #endif /* CONFIG_NO_RADIUS */
3137 	} else if (os_strcmp(buf, "auth_algs") == 0) {
3138 		bss->auth_algs = atoi(pos);
3139 		if (bss->auth_algs == 0) {
3140 			wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed",
3141 				   line);
3142 			return 1;
3143 		}
3144 	} else if (os_strcmp(buf, "max_num_sta") == 0) {
3145 		bss->max_num_sta = atoi(pos);
3146 		if (bss->max_num_sta < 0 ||
3147 		    bss->max_num_sta > MAX_STA_COUNT) {
3148 			wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
3149 				   line, bss->max_num_sta, MAX_STA_COUNT);
3150 			return 1;
3151 		}
3152 	} else if (os_strcmp(buf, "wpa") == 0) {
3153 		bss->wpa = atoi(pos);
3154 	} else if (os_strcmp(buf, "extended_key_id") == 0) {
3155 		int val = atoi(pos);
3156 
3157 		if (val < 0 || val > 2) {
3158 			wpa_printf(MSG_ERROR,
3159 				   "Line %d: Invalid extended_key_id=%d; allowed range 0..2",
3160 				   line, val);
3161 			return 1;
3162 		}
3163 		bss->extended_key_id = val;
3164 	} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
3165 		bss->wpa_group_rekey = atoi(pos);
3166 		bss->wpa_group_rekey_set = 1;
3167 	} else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
3168 		bss->wpa_strict_rekey = atoi(pos);
3169 	} else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
3170 		bss->wpa_gmk_rekey = atoi(pos);
3171 	} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
3172 		bss->wpa_ptk_rekey = atoi(pos);
3173 	} else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
3174 		bss->wpa_deny_ptk0_rekey = atoi(pos);
3175 		if (bss->wpa_deny_ptk0_rekey < 0 ||
3176 		    bss->wpa_deny_ptk0_rekey > 2) {
3177 			wpa_printf(MSG_ERROR,
3178 				   "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
3179 				   line, bss->wpa_deny_ptk0_rekey);
3180 			return 1;
3181 		}
3182 	} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
3183 		char *endp;
3184 		unsigned long val = strtoul(pos, &endp, 0);
3185 
3186 		if (*endp || val < 1 || val > (u32) -1) {
3187 			wpa_printf(MSG_ERROR,
3188 				   "Line %d: Invalid wpa_group_update_count=%lu; allowed range 1..4294967295",
3189 				   line, val);
3190 			return 1;
3191 		}
3192 		bss->wpa_group_update_count = (u32) val;
3193 	} else if (os_strcmp(buf, "wpa_pairwise_update_count") == 0) {
3194 		char *endp;
3195 		unsigned long val = strtoul(pos, &endp, 0);
3196 
3197 		if (*endp || val < 1 || val > (u32) -1) {
3198 			wpa_printf(MSG_ERROR,
3199 				   "Line %d: Invalid wpa_pairwise_update_count=%lu; allowed range 1..4294967295",
3200 				   line, val);
3201 			return 1;
3202 		}
3203 		bss->wpa_pairwise_update_count = (u32) val;
3204 	} else if (os_strcmp(buf, "wpa_disable_eapol_key_retries") == 0) {
3205 		bss->wpa_disable_eapol_key_retries = atoi(pos);
3206 	} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
3207 		int len = os_strlen(pos);
3208 		if (len < 8 || len > 63) {
3209 			wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)",
3210 				   line, len);
3211 			return 1;
3212 		}
3213 		os_free(bss->ssid.wpa_passphrase);
3214 		bss->ssid.wpa_passphrase = os_strdup(pos);
3215 		if (bss->ssid.wpa_passphrase) {
3216 			hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
3217 			bss->ssid.wpa_passphrase_set = 1;
3218 		}
3219 	} else if (os_strcmp(buf, "wpa_psk") == 0) {
3220 		hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
3221 		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
3222 		if (bss->ssid.wpa_psk == NULL)
3223 			return 1;
3224 		if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) ||
3225 		    pos[PMK_LEN * 2] != '\0') {
3226 			wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
3227 				   line, pos);
3228 			hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
3229 			return 1;
3230 		}
3231 		bss->ssid.wpa_psk->group = 1;
3232 		os_free(bss->ssid.wpa_passphrase);
3233 		bss->ssid.wpa_passphrase = NULL;
3234 		bss->ssid.wpa_psk_set = 1;
3235 	} else if (os_strcmp(buf, "wpa_psk_file") == 0) {
3236 		os_free(bss->ssid.wpa_psk_file);
3237 		bss->ssid.wpa_psk_file = os_strdup(pos);
3238 		if (!bss->ssid.wpa_psk_file) {
3239 			wpa_printf(MSG_ERROR, "Line %d: allocation failed",
3240 				   line);
3241 			return 1;
3242 		}
3243 	} else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
3244 		bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
3245 		if (bss->wpa_key_mgmt == -1)
3246 			return 1;
3247 	} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
3248 		bss->wpa_psk_radius = atoi(pos);
3249 		if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
3250 		    bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
3251 		    bss->wpa_psk_radius != PSK_RADIUS_REQUIRED &&
3252 		    bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS) {
3253 			wpa_printf(MSG_ERROR,
3254 				   "Line %d: unknown wpa_psk_radius %d",
3255 				   line, bss->wpa_psk_radius);
3256 			return 1;
3257 		}
3258 	} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
3259 		bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos);
3260 		if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0)
3261 			return 1;
3262 		if (bss->wpa_pairwise &
3263 		    (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
3264 			wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
3265 				   line, pos);
3266 			return 1;
3267 		}
3268 	} else if (os_strcmp(buf, "rsn_pairwise") == 0) {
3269 		bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos);
3270 		if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0)
3271 			return 1;
3272 		if (bss->rsn_pairwise &
3273 		    (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
3274 			wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
3275 				   line, pos);
3276 			return 1;
3277 		}
3278 	} else if (os_strcmp(buf, "group_cipher") == 0) {
3279 		bss->group_cipher = hostapd_config_parse_cipher(line, pos);
3280 		if (bss->group_cipher == -1 || bss->group_cipher == 0)
3281 			return 1;
3282 		if (bss->group_cipher != WPA_CIPHER_TKIP &&
3283 		    bss->group_cipher != WPA_CIPHER_CCMP &&
3284 		    bss->group_cipher != WPA_CIPHER_GCMP &&
3285 		    bss->group_cipher != WPA_CIPHER_GCMP_256 &&
3286 		    bss->group_cipher != WPA_CIPHER_CCMP_256) {
3287 			wpa_printf(MSG_ERROR,
3288 				   "Line %d: unsupported group cipher suite '%s'",
3289 				   line, pos);
3290 			return 1;
3291 		}
3292 #ifdef CONFIG_RSN_PREAUTH
3293 	} else if (os_strcmp(buf, "rsn_preauth") == 0) {
3294 		bss->rsn_preauth = atoi(pos);
3295 	} else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
3296 		os_free(bss->rsn_preauth_interfaces);
3297 		bss->rsn_preauth_interfaces = os_strdup(pos);
3298 #endif /* CONFIG_RSN_PREAUTH */
3299 	} else if (os_strcmp(buf, "peerkey") == 0) {
3300 		wpa_printf(MSG_INFO,
3301 			   "Line %d: Obsolete peerkey parameter ignored", line);
3302 #ifdef CONFIG_IEEE80211R_AP
3303 	} else if (os_strcmp(buf, "mobility_domain") == 0) {
3304 		if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
3305 		    hexstr2bin(pos, bss->mobility_domain,
3306 			       MOBILITY_DOMAIN_ID_LEN) != 0) {
3307 			wpa_printf(MSG_ERROR,
3308 				   "Line %d: Invalid mobility_domain '%s'",
3309 				   line, pos);
3310 			return 1;
3311 		}
3312 	} else if (os_strcmp(buf, "r1_key_holder") == 0) {
3313 		if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
3314 		    hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) {
3315 			wpa_printf(MSG_ERROR,
3316 				   "Line %d: Invalid r1_key_holder '%s'",
3317 				   line, pos);
3318 			return 1;
3319 		}
3320 	} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
3321 		/* DEPRECATED: Use ft_r0_key_lifetime instead. */
3322 		bss->r0_key_lifetime = atoi(pos) * 60;
3323 	} else if (os_strcmp(buf, "ft_r0_key_lifetime") == 0) {
3324 		bss->r0_key_lifetime = atoi(pos);
3325 	} else if (os_strcmp(buf, "r1_max_key_lifetime") == 0) {
3326 		bss->r1_max_key_lifetime = atoi(pos);
3327 	} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
3328 		bss->reassociation_deadline = atoi(pos);
3329 	} else if (os_strcmp(buf, "rkh_pos_timeout") == 0) {
3330 		bss->rkh_pos_timeout = atoi(pos);
3331 	} else if (os_strcmp(buf, "rkh_neg_timeout") == 0) {
3332 		bss->rkh_neg_timeout = atoi(pos);
3333 	} else if (os_strcmp(buf, "rkh_pull_timeout") == 0) {
3334 		bss->rkh_pull_timeout = atoi(pos);
3335 	} else if (os_strcmp(buf, "rkh_pull_retries") == 0) {
3336 		bss->rkh_pull_retries = atoi(pos);
3337 	} else if (os_strcmp(buf, "r0kh") == 0) {
3338 		if (add_r0kh(bss, pos) < 0) {
3339 			wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'",
3340 				   line, pos);
3341 			return 1;
3342 		}
3343 	} else if (os_strcmp(buf, "r1kh") == 0) {
3344 		if (add_r1kh(bss, pos) < 0) {
3345 			wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'",
3346 				   line, pos);
3347 			return 1;
3348 		}
3349 	} else if (os_strcmp(buf, "rxkh_file") == 0) {
3350 		os_free(bss->rxkh_file);
3351 		bss->rxkh_file = os_strdup(pos);
3352 		if (!bss->rxkh_file) {
3353 			wpa_printf(MSG_ERROR, "Line %d: allocation failed",
3354 				   line);
3355 			return 1;
3356 		}
3357 		if (hostapd_config_read_rxkh_file(bss, pos)) {
3358 			wpa_printf(MSG_DEBUG,
3359 				   "Line %d: failed to read rxkh_file '%s'",
3360 				   line, pos);
3361 			/* Allow the file to be created later and read into
3362 			 * already operating AP context. */
3363 		}
3364 	} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
3365 		bss->pmk_r1_push = atoi(pos);
3366 	} else if (os_strcmp(buf, "ft_over_ds") == 0) {
3367 		bss->ft_over_ds = atoi(pos);
3368 	} else if (os_strcmp(buf, "ft_psk_generate_local") == 0) {
3369 		bss->ft_psk_generate_local = atoi(pos);
3370 #endif /* CONFIG_IEEE80211R_AP */
3371 #ifndef CONFIG_NO_CTRL_IFACE
3372 	} else if (os_strcmp(buf, "ctrl_interface") == 0) {
3373 		os_free(bss->ctrl_interface);
3374 		bss->ctrl_interface = os_strdup(pos);
3375 	} else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
3376 #ifndef CONFIG_NATIVE_WINDOWS
3377 		struct group *grp;
3378 		char *endp;
3379 		const char *group = pos;
3380 
3381 		grp = getgrnam(group);
3382 		if (grp) {
3383 			bss->ctrl_interface_gid = grp->gr_gid;
3384 			bss->ctrl_interface_gid_set = 1;
3385 			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')",
3386 				   bss->ctrl_interface_gid, group);
3387 			return 0;
3388 		}
3389 
3390 		/* Group name not found - try to parse this as gid */
3391 		bss->ctrl_interface_gid = strtol(group, &endp, 10);
3392 		if (*group == '\0' || *endp != '\0') {
3393 			wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'",
3394 				   line, group);
3395 			return 1;
3396 		}
3397 		bss->ctrl_interface_gid_set = 1;
3398 		wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
3399 			   bss->ctrl_interface_gid);
3400 #endif /* CONFIG_NATIVE_WINDOWS */
3401 #endif /* CONFIG_NO_CTRL_IFACE */
3402 #ifdef RADIUS_SERVER
3403 	} else if (os_strcmp(buf, "radius_server_clients") == 0) {
3404 		os_free(bss->radius_server_clients);
3405 		bss->radius_server_clients = os_strdup(pos);
3406 	} else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
3407 		bss->radius_server_auth_port = atoi(pos);
3408 	} else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
3409 		bss->radius_server_acct_port = atoi(pos);
3410 	} else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
3411 		bss->radius_server_ipv6 = atoi(pos);
3412 #endif /* RADIUS_SERVER */
3413 	} else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
3414 		bss->use_pae_group_addr = atoi(pos);
3415 	} else if (os_strcmp(buf, "hw_mode") == 0) {
3416 		if (os_strcmp(pos, "a") == 0)
3417 			conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
3418 		else if (os_strcmp(pos, "b") == 0)
3419 			conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
3420 		else if (os_strcmp(pos, "g") == 0)
3421 			conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
3422 		else if (os_strcmp(pos, "ad") == 0)
3423 			conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
3424 		else if (os_strcmp(pos, "any") == 0)
3425 			conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
3426 		else {
3427 			wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
3428 				   line, pos);
3429 			return 1;
3430 		}
3431 		conf->hw_mode_set = true;
3432 	} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
3433 		if (os_strcmp(pos, "ad") == 0)
3434 			bss->wps_rf_bands = WPS_RF_60GHZ;
3435 		else if (os_strcmp(pos, "a") == 0)
3436 			bss->wps_rf_bands = WPS_RF_50GHZ;
3437 		else if (os_strcmp(pos, "g") == 0 ||
3438 			 os_strcmp(pos, "b") == 0)
3439 			bss->wps_rf_bands = WPS_RF_24GHZ;
3440 		else if (os_strcmp(pos, "ag") == 0 ||
3441 			 os_strcmp(pos, "ga") == 0)
3442 			bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
3443 		else {
3444 			wpa_printf(MSG_ERROR,
3445 				   "Line %d: unknown wps_rf_band '%s'",
3446 				   line, pos);
3447 			return 1;
3448 		}
3449 	} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
3450 		conf->acs_exclude_dfs = atoi(pos);
3451 	} else if (os_strcmp(buf, "op_class") == 0) {
3452 		conf->op_class = atoi(pos);
3453 	} else if (os_strcmp(buf, "channel") == 0) {
3454 		if (os_strcmp(pos, "acs_survey") == 0) {
3455 #ifndef CONFIG_ACS
3456 			wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled",
3457 				   line);
3458 			return 1;
3459 #else /* CONFIG_ACS */
3460 			conf->acs = 1;
3461 			conf->channel = 0;
3462 #endif /* CONFIG_ACS */
3463 		} else {
3464 #ifdef CONFIG_OPEN_HARMONY_PATCH
3465 			int chan_info = atoi(pos);
3466 			conf->channel = (u8)(chan_info & 0x000000FF);
3467 			conf->bandwidth = (u8)((chan_info & 0x00FF0000) >> 16);
3468 			wpa_printf(MSG_DEBUG, "ap_config_file channel %d, bandwidth %d",
3469 				conf->channel, conf->bandwidth);
3470 #else
3471 			conf->channel = atoi(pos);
3472 #endif
3473 			conf->acs = conf->channel == 0;
3474 			hostapd_config_bw_auto_adaptation(conf);
3475 		}
3476 	} else if (os_strcmp(buf, "edmg_channel") == 0) {
3477 		conf->edmg_channel = atoi(pos);
3478 	} else if (os_strcmp(buf, "enable_edmg") == 0) {
3479 		conf->enable_edmg = atoi(pos);
3480 	} else if (os_strcmp(buf, "chanlist") == 0) {
3481 		if (hostapd_parse_chanlist(conf, pos)) {
3482 			wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
3483 				   line);
3484 			return 1;
3485 		}
3486 	} else if (os_strcmp(buf, "freqlist") == 0) {
3487 		if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
3488 			wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
3489 				   line);
3490 			return 1;
3491 		}
3492 		conf->acs_freq_list_present = 1;
3493 	} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
3494 		conf->acs_exclude_6ghz_non_psc = atoi(pos);
3495 	} else if (os_strcmp(buf, "enable_background_radar") == 0) {
3496 		conf->enable_background_radar = atoi(pos);
3497 	} else if (os_strcmp(buf, "min_tx_power") == 0) {
3498 		int val = atoi(pos);
3499 
3500 		if (val < 0 || val > 255) {
3501 			wpa_printf(MSG_ERROR,
3502 				   "Line %d: invalid min_tx_power %d (expected 0..255)",
3503 				   line, val);
3504 			return 1;
3505 		}
3506 		conf->min_tx_power = val;
3507 	} else if (os_strcmp(buf, "beacon_int") == 0) {
3508 		int val = atoi(pos);
3509 		/* MIB defines range as 1..65535, but very small values
3510 		 * cause problems with the current implementation.
3511 		 * Since it is unlikely that this small numbers are
3512 		 * useful in real life scenarios, do not allow beacon
3513 		 * period to be set below 10 TU. */
3514 		if (val < 10 || val > 65535) {
3515 			wpa_printf(MSG_ERROR,
3516 				   "Line %d: invalid beacon_int %d (expected 10..65535)",
3517 				   line, val);
3518 			return 1;
3519 		}
3520 		conf->beacon_int = val;
3521 #ifdef CONFIG_ACS
3522 	} else if (os_strcmp(buf, "acs_num_scans") == 0) {
3523 		int val = atoi(pos);
3524 		if (val <= 0 || val > 100) {
3525 			wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)",
3526 				   line, val);
3527 			return 1;
3528 		}
3529 		conf->acs_num_scans = val;
3530 	} else if (os_strcmp(buf, "acs_chan_bias") == 0) {
3531 		if (hostapd_config_parse_acs_chan_bias(conf, pos)) {
3532 			wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias",
3533 				   line);
3534 			return -1;
3535 		}
3536 #endif /* CONFIG_ACS */
3537 	} else if (os_strcmp(buf, "dtim_period") == 0) {
3538 		int val = atoi(pos);
3539 
3540 		if (val < 1 || val > 255) {
3541 			wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d",
3542 				   line, val);
3543 			return 1;
3544 		}
3545 		bss->dtim_period = val;
3546 	} else if (os_strcmp(buf, "bss_load_update_period") == 0) {
3547 		int val = atoi(pos);
3548 
3549 		if (val < 0 || val > 100) {
3550 			wpa_printf(MSG_ERROR,
3551 				   "Line %d: invalid bss_load_update_period %d",
3552 				   line, val);
3553 			return 1;
3554 		}
3555 		bss->bss_load_update_period = val;
3556 	} else if (os_strcmp(buf, "chan_util_avg_period") == 0) {
3557 		int val = atoi(pos);
3558 
3559 		if (val < 0) {
3560 			wpa_printf(MSG_ERROR,
3561 				   "Line %d: invalid chan_util_avg_period",
3562 				   line);
3563 			return 1;
3564 		}
3565 		bss->chan_util_avg_period = val;
3566 	} else if (os_strcmp(buf, "rts_threshold") == 0) {
3567 		conf->rts_threshold = atoi(pos);
3568 		if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) {
3569 			wpa_printf(MSG_ERROR,
3570 				   "Line %d: invalid rts_threshold %d",
3571 				   line, conf->rts_threshold);
3572 			return 1;
3573 		}
3574 	} else if (os_strcmp(buf, "fragm_threshold") == 0) {
3575 		conf->fragm_threshold = atoi(pos);
3576 		if (conf->fragm_threshold == -1) {
3577 			/* allow a value of -1 */
3578 		} else if (conf->fragm_threshold < 256 ||
3579 			   conf->fragm_threshold > 2346) {
3580 			wpa_printf(MSG_ERROR,
3581 				   "Line %d: invalid fragm_threshold %d",
3582 				   line, conf->fragm_threshold);
3583 			return 1;
3584 		}
3585 	} else if (os_strcmp(buf, "send_probe_response") == 0) {
3586 		int val = atoi(pos);
3587 		if (val != 0 && val != 1) {
3588 			wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)",
3589 				   line, val);
3590 			return 1;
3591 		}
3592 		bss->send_probe_response = val;
3593 	} else if (os_strcmp(buf, "supported_rates") == 0) {
3594 		if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
3595 			wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
3596 				   line);
3597 			return 1;
3598 		}
3599 	} else if (os_strcmp(buf, "basic_rates") == 0) {
3600 		if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
3601 			wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
3602 				   line);
3603 			return 1;
3604 		}
3605 	} else if (os_strcmp(buf, "beacon_rate") == 0) {
3606 		int val;
3607 
3608 		if (os_strncmp(pos, "ht:", 3) == 0) {
3609 			val = atoi(pos + 3);
3610 			if (val < 0 || val > 31) {
3611 				wpa_printf(MSG_ERROR,
3612 					   "Line %d: invalid beacon_rate HT-MCS %d",
3613 					   line, val);
3614 				return 1;
3615 			}
3616 			conf->rate_type = BEACON_RATE_HT;
3617 			conf->beacon_rate = val;
3618 		} else if (os_strncmp(pos, "vht:", 4) == 0) {
3619 			val = atoi(pos + 4);
3620 			if (val < 0 || val > 9) {
3621 				wpa_printf(MSG_ERROR,
3622 					   "Line %d: invalid beacon_rate VHT-MCS %d",
3623 					   line, val);
3624 				return 1;
3625 			}
3626 			conf->rate_type = BEACON_RATE_VHT;
3627 			conf->beacon_rate = val;
3628 		} else if (os_strncmp(pos, "he:", 3) == 0) {
3629 			val = atoi(pos + 3);
3630 			if (val < 0 || val > 11) {
3631 				wpa_printf(MSG_ERROR,
3632 					   "Line %d: invalid beacon_rate HE-MCS %d",
3633 					   line, val);
3634 				return 1;
3635 			}
3636 			conf->rate_type = BEACON_RATE_HE;
3637 			conf->beacon_rate = val;
3638 		} else {
3639 			val = atoi(pos);
3640 			if (val < 10 || val > 10000) {
3641 				wpa_printf(MSG_ERROR,
3642 					   "Line %d: invalid legacy beacon_rate %d",
3643 					   line, val);
3644 				return 1;
3645 			}
3646 			conf->rate_type = BEACON_RATE_LEGACY;
3647 			conf->beacon_rate = val;
3648 		}
3649 	} else if (os_strcmp(buf, "preamble") == 0) {
3650 		if (atoi(pos))
3651 			conf->preamble = SHORT_PREAMBLE;
3652 		else
3653 			conf->preamble = LONG_PREAMBLE;
3654 	} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
3655 		bss->ignore_broadcast_ssid = atoi(pos);
3656 	} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
3657 		bss->no_probe_resp_if_max_sta = atoi(pos);
3658 #ifdef CONFIG_WEP
3659 	} else if (os_strcmp(buf, "wep_default_key") == 0) {
3660 		bss->ssid.wep.idx = atoi(pos);
3661 		if (bss->ssid.wep.idx > 3) {
3662 			wpa_printf(MSG_ERROR,
3663 				   "Invalid wep_default_key index %d",
3664 				   bss->ssid.wep.idx);
3665 			return 1;
3666 		}
3667 	} else if (os_strcmp(buf, "wep_key0") == 0 ||
3668 		   os_strcmp(buf, "wep_key1") == 0 ||
3669 		   os_strcmp(buf, "wep_key2") == 0 ||
3670 		   os_strcmp(buf, "wep_key3") == 0) {
3671 		if (hostapd_config_read_wep(&bss->ssid.wep,
3672 					    buf[7] - '0', pos)) {
3673 			wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'",
3674 				   line, buf);
3675 			return 1;
3676 		}
3677 #endif /* CONFIG_WEP */
3678 #ifndef CONFIG_NO_VLAN
3679 	} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
3680 		bss->ssid.dynamic_vlan = atoi(pos);
3681 	} else if (os_strcmp(buf, "per_sta_vif") == 0) {
3682 		bss->ssid.per_sta_vif = atoi(pos);
3683 	} else if (os_strcmp(buf, "vlan_file") == 0) {
3684 		if (hostapd_config_read_vlan_file(bss, pos)) {
3685 			wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
3686 				   line, pos);
3687 			return 1;
3688 		}
3689 	} else if (os_strcmp(buf, "vlan_naming") == 0) {
3690 		bss->ssid.vlan_naming = atoi(pos);
3691 		if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
3692 		    bss->ssid.vlan_naming < 0) {
3693 			wpa_printf(MSG_ERROR,
3694 				   "Line %d: invalid naming scheme %d",
3695 				   line, bss->ssid.vlan_naming);
3696 			return 1;
3697 		}
3698 #ifdef CONFIG_FULL_DYNAMIC_VLAN
3699 	} else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
3700 		os_free(bss->ssid.vlan_tagged_interface);
3701 		bss->ssid.vlan_tagged_interface = os_strdup(pos);
3702 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
3703 #endif /* CONFIG_NO_VLAN */
3704 	} else if (os_strcmp(buf, "ap_table_max_size") == 0) {
3705 		conf->ap_table_max_size = atoi(pos);
3706 	} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
3707 		conf->ap_table_expiration_time = atoi(pos);
3708 	} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
3709 		if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) {
3710 			wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
3711 				   line);
3712 			return 1;
3713 		}
3714 	} else if (os_strcmp(buf, "wme_enabled") == 0 ||
3715 		   os_strcmp(buf, "wmm_enabled") == 0) {
3716 		bss->wmm_enabled = atoi(pos);
3717 	} else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
3718 		bss->wmm_uapsd = atoi(pos);
3719 	} else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
3720 		   os_strncmp(buf, "wmm_ac_", 7) == 0) {
3721 		if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) {
3722 			wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item",
3723 				   line);
3724 			return 1;
3725 		}
3726 	} else if (os_strcmp(buf, "bss") == 0) {
3727 		if (hostapd_config_bss(conf, pos)) {
3728 			wpa_printf(MSG_ERROR, "Line %d: invalid bss item",
3729 				   line);
3730 			return 1;
3731 		}
3732 	} else if (os_strcmp(buf, "bssid") == 0) {
3733 		if (hwaddr_aton(pos, bss->bssid)) {
3734 			wpa_printf(MSG_ERROR, "Line %d: invalid bssid item",
3735 				   line);
3736 			return 1;
3737 		}
3738 	} else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
3739 		conf->use_driver_iface_addr = atoi(pos);
3740 	} else if (os_strcmp(buf, "ieee80211w") == 0) {
3741 		bss->ieee80211w = atoi(pos);
3742 	} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
3743 		if (os_strcmp(pos, "AES-128-CMAC") == 0) {
3744 			bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
3745 		} else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
3746 			bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
3747 		} else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
3748 			bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
3749 		} else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
3750 			bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
3751 		} else {
3752 			wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
3753 				   line, pos);
3754 			return 1;
3755 		}
3756 	} else if (os_strcmp(buf, "beacon_prot") == 0) {
3757 		bss->beacon_prot = atoi(pos);
3758 	} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
3759 		bss->assoc_sa_query_max_timeout = atoi(pos);
3760 		if (bss->assoc_sa_query_max_timeout == 0) {
3761 			wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout",
3762 				   line);
3763 			return 1;
3764 		}
3765 	} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) {
3766 		bss->assoc_sa_query_retry_timeout = atoi(pos);
3767 		if (bss->assoc_sa_query_retry_timeout == 0) {
3768 			wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout",
3769 				   line);
3770 			return 1;
3771 		}
3772 #ifdef CONFIG_OCV
3773 	} else if (os_strcmp(buf, "ocv") == 0) {
3774 		bss->ocv = atoi(pos);
3775 		if (bss->ocv && !bss->ieee80211w)
3776 			bss->ieee80211w = 1;
3777 #endif /* CONFIG_OCV */
3778 	} else if (os_strcmp(buf, "ieee80211n") == 0) {
3779 		conf->ieee80211n = atoi(pos);
3780 	} else if (os_strcmp(buf, "ht_capab") == 0) {
3781 		if (hostapd_config_ht_capab(conf, pos) < 0) {
3782 			wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab",
3783 				   line);
3784 			return 1;
3785 		}
3786 	} else if (os_strcmp(buf, "require_ht") == 0) {
3787 		conf->require_ht = atoi(pos);
3788 	} else if (os_strcmp(buf, "ht_vht_twt_responder") == 0) {
3789 		conf->ht_vht_twt_responder = atoi(pos);
3790 	} else if (os_strcmp(buf, "obss_interval") == 0) {
3791 		conf->obss_interval = atoi(pos);
3792 #ifdef CONFIG_IEEE80211AC
3793 	} else if (os_strcmp(buf, "ieee80211ac") == 0) {
3794 		conf->ieee80211ac = atoi(pos);
3795 	} else if (os_strcmp(buf, "vht_capab") == 0) {
3796 		if (hostapd_config_vht_capab(conf, pos) < 0) {
3797 			wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab",
3798 				   line);
3799 			return 1;
3800 		}
3801 	} else if (os_strcmp(buf, "require_vht") == 0) {
3802 		conf->require_vht = atoi(pos);
3803 	} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
3804 		conf->vht_oper_chwidth = atoi(pos);
3805 	} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
3806 		conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
3807 	} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) {
3808 		conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
3809 	} else if (os_strcmp(buf, "vendor_vht") == 0) {
3810 		bss->vendor_vht = atoi(pos);
3811 	} else if (os_strcmp(buf, "use_sta_nsts") == 0) {
3812 		bss->use_sta_nsts = atoi(pos);
3813 #endif /* CONFIG_IEEE80211AC */
3814 #ifdef CONFIG_IEEE80211AX
3815 	} else if (os_strcmp(buf, "ieee80211ax") == 0) {
3816 		conf->ieee80211ax = atoi(pos);
3817 	} else if (os_strcmp(buf, "require_he") == 0) {
3818 		conf->require_he = atoi(pos);
3819 	} else if (os_strcmp(buf, "he_su_beamformer") == 0) {
3820 		conf->he_phy_capab.he_su_beamformer = atoi(pos);
3821 	} else if (os_strcmp(buf, "he_su_beamformee") == 0) {
3822 		conf->he_phy_capab.he_su_beamformee = atoi(pos);
3823 	} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
3824 		conf->he_phy_capab.he_mu_beamformer = atoi(pos);
3825 	} else if (os_strcmp(buf, "he_bss_color") == 0) {
3826 		conf->he_op.he_bss_color = atoi(pos) & 0x3f;
3827 		conf->he_op.he_bss_color_disabled = 0;
3828 	} else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
3829 		conf->he_op.he_bss_color_partial = atoi(pos);
3830 	} else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
3831 		conf->he_op.he_default_pe_duration = atoi(pos);
3832 	} else if (os_strcmp(buf, "he_twt_required") == 0) {
3833 		conf->he_op.he_twt_required = atoi(pos);
3834 	} else if (os_strcmp(buf, "he_twt_responder") == 0) {
3835 		conf->he_op.he_twt_responder = atoi(pos);
3836 	} else if (os_strcmp(buf, "he_rts_threshold") == 0) {
3837 		conf->he_op.he_rts_threshold = atoi(pos);
3838 	} else if (os_strcmp(buf, "he_er_su_disable") == 0) {
3839 		conf->he_op.he_er_su_disable = atoi(pos);
3840 	} else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) {
3841 		conf->he_op.he_basic_mcs_nss_set = atoi(pos);
3842 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) {
3843 		conf->he_mu_edca.he_qos_info |=
3844 			set_he_cap(atoi(pos), HE_QOS_INFO_EDCA_PARAM_SET_COUNT);
3845 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_q_ack") == 0) {
3846 		conf->he_mu_edca.he_qos_info |=
3847 			set_he_cap(atoi(pos), HE_QOS_INFO_Q_ACK);
3848 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_queue_request") == 0) {
3849 		conf->he_mu_edca.he_qos_info |=
3850 			set_he_cap(atoi(pos), HE_QOS_INFO_QUEUE_REQUEST);
3851 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_txop_request") == 0) {
3852 		conf->he_mu_edca.he_qos_info |=
3853 			set_he_cap(atoi(pos), HE_QOS_INFO_TXOP_REQUEST);
3854 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_aifsn") == 0) {
3855 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
3856 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
3857 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_acm") == 0) {
3858 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
3859 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
3860 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_aci") == 0) {
3861 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
3862 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
3863 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmin") == 0) {
3864 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
3865 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
3866 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmax") == 0) {
3867 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
3868 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
3869 	} else if (os_strcmp(buf, "he_mu_edca_ac_be_timer") == 0) {
3870 		conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] =
3871 			atoi(pos) & 0xff;
3872 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_aifsn") == 0) {
3873 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
3874 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
3875 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_acm") == 0) {
3876 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
3877 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
3878 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_aci") == 0) {
3879 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
3880 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
3881 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmin") == 0) {
3882 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
3883 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
3884 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmax") == 0) {
3885 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
3886 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
3887 	} else if (os_strcmp(buf, "he_mu_edca_ac_bk_timer") == 0) {
3888 		conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] =
3889 			atoi(pos) & 0xff;
3890 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_aifsn") == 0) {
3891 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
3892 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
3893 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_acm") == 0) {
3894 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
3895 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
3896 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_aci") == 0) {
3897 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
3898 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
3899 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmin") == 0) {
3900 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
3901 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
3902 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmax") == 0) {
3903 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
3904 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
3905 	} else if (os_strcmp(buf, "he_mu_edca_ac_vi_timer") == 0) {
3906 		conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] =
3907 			atoi(pos) & 0xff;
3908 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_aifsn") == 0) {
3909 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
3910 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
3911 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_acm") == 0) {
3912 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
3913 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
3914 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_aci") == 0) {
3915 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
3916 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
3917 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmin") == 0) {
3918 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
3919 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
3920 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmax") == 0) {
3921 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
3922 			set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
3923 	} else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) {
3924 		conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] =
3925 			atoi(pos) & 0xff;
3926 	} else if (os_strcmp(buf, "he_spr_sr_control") == 0) {
3927 		conf->spr.sr_control = atoi(pos) & 0x1f;
3928 	} else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) {
3929 		conf->spr.non_srg_obss_pd_max_offset = atoi(pos);
3930 	} else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) {
3931 		conf->spr.srg_obss_pd_min_offset = atoi(pos);
3932 	} else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) {
3933 		conf->spr.srg_obss_pd_max_offset = atoi(pos);
3934 	} else if (os_strcmp(buf, "he_spr_srg_bss_colors") == 0) {
3935 		if (hostapd_parse_he_srg_bitmap(
3936 			conf->spr.srg_bss_color_bitmap, pos)) {
3937 			wpa_printf(MSG_ERROR,
3938 				   "Line %d: Invalid srg bss colors list '%s'",
3939 				   line, pos);
3940 			return 1;
3941 		}
3942 	} else if (os_strcmp(buf, "he_spr_srg_partial_bssid") == 0) {
3943 		if (hostapd_parse_he_srg_bitmap(
3944 			conf->spr.srg_partial_bssid_bitmap, pos)) {
3945 			wpa_printf(MSG_ERROR,
3946 				   "Line %d: Invalid srg partial bssid list '%s'",
3947 				   line, pos);
3948 			return 1;
3949 		}
3950 	} else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) {
3951 		conf->he_6ghz_reg_pwr_type = atoi(pos);
3952 		if (conf->he_6ghz_reg_pwr_type > HE_REG_INFO_6GHZ_AP_TYPE_MAX) {
3953 			wpa_printf(MSG_ERROR,
3954 				   "Line %d: invalid he_6ghz_reg_pwr_type value",
3955 				   line);
3956 			return 1;
3957 		}
3958 	} else if (os_strcmp(buf, "reg_def_cli_eirp_psd") == 0) {
3959 		conf->reg_def_cli_eirp_psd = atoi(pos);
3960 	} else if (os_strcmp(buf, "reg_sub_cli_eirp_psd") == 0) {
3961 		conf->reg_sub_cli_eirp_psd = atoi(pos);
3962 	} else if (os_strcmp(buf, "reg_def_cli_eirp") == 0) {
3963 		conf->reg_def_cli_eirp = atoi(pos);
3964 	} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
3965 		conf->he_oper_chwidth = atoi(pos);
3966 	} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
3967 		conf->he_oper_centr_freq_seg0_idx = atoi(pos);
3968 	} else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) {
3969 		conf->he_oper_centr_freq_seg1_idx = atoi(pos);
3970 	} else if (os_strcmp(buf, "he_6ghz_max_mpdu") == 0) {
3971 		conf->he_6ghz_max_mpdu = atoi(pos);
3972 	} else if (os_strcmp(buf, "he_6ghz_max_ampdu_len_exp") == 0) {
3973 		conf->he_6ghz_max_ampdu_len_exp = atoi(pos);
3974 	} else if (os_strcmp(buf, "he_6ghz_rx_ant_pat") == 0) {
3975 		conf->he_6ghz_rx_ant_pat = atoi(pos);
3976 	} else if (os_strcmp(buf, "he_6ghz_tx_ant_pat") == 0) {
3977 		conf->he_6ghz_tx_ant_pat = atoi(pos);
3978 	} else if (os_strcmp(buf, "unsol_bcast_probe_resp_interval") == 0) {
3979 		int val = atoi(pos);
3980 
3981 		if (val < 0 || val > 20) {
3982 			wpa_printf(MSG_ERROR,
3983 				   "Line %d: invalid unsol_bcast_probe_resp_interval value",
3984 				   line);
3985 			return 1;
3986 		}
3987 		bss->unsol_bcast_probe_resp_interval = val;
3988 	} else if (os_strcmp(buf, "mbssid") == 0) {
3989 		int mbssid = atoi(pos);
3990 		if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
3991 			wpa_printf(MSG_ERROR,
3992 				   "Line %d: invalid mbssid (%d): '%s'.",
3993 				   line, mbssid, pos);
3994 			return 1;
3995 		}
3996 		conf->mbssid = mbssid;
3997 #endif /* CONFIG_IEEE80211AX */
3998 	} else if (os_strcmp(buf, "max_listen_interval") == 0) {
3999 		bss->max_listen_interval = atoi(pos);
4000 	} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
4001 		bss->disable_pmksa_caching = atoi(pos);
4002 	} else if (os_strcmp(buf, "okc") == 0) {
4003 		bss->okc = atoi(pos);
4004 #ifdef CONFIG_WPS
4005 	} else if (os_strcmp(buf, "wps_state") == 0) {
4006 		bss->wps_state = atoi(pos);
4007 		if (bss->wps_state < 0 || bss->wps_state > 2) {
4008 			wpa_printf(MSG_ERROR, "Line %d: invalid wps_state",
4009 				   line);
4010 			return 1;
4011 		}
4012 	} else if (os_strcmp(buf, "wps_independent") == 0) {
4013 		bss->wps_independent = atoi(pos);
4014 	} else if (os_strcmp(buf, "ap_setup_locked") == 0) {
4015 		bss->ap_setup_locked = atoi(pos);
4016 	} else if (os_strcmp(buf, "uuid") == 0) {
4017 		if (uuid_str2bin(pos, bss->uuid)) {
4018 			wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
4019 			return 1;
4020 		}
4021 	} else if (os_strcmp(buf, "wps_pin_requests") == 0) {
4022 		os_free(bss->wps_pin_requests);
4023 		bss->wps_pin_requests = os_strdup(pos);
4024 	} else if (os_strcmp(buf, "device_name") == 0) {
4025 		if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) {
4026 			wpa_printf(MSG_ERROR, "Line %d: Too long "
4027 				   "device_name", line);
4028 			return 1;
4029 		}
4030 		os_free(bss->device_name);
4031 		bss->device_name = os_strdup(pos);
4032 	} else if (os_strcmp(buf, "manufacturer") == 0) {
4033 		if (os_strlen(pos) > 64) {
4034 			wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer",
4035 				   line);
4036 			return 1;
4037 		}
4038 		os_free(bss->manufacturer);
4039 		bss->manufacturer = os_strdup(pos);
4040 	} else if (os_strcmp(buf, "model_name") == 0) {
4041 		if (os_strlen(pos) > 32) {
4042 			wpa_printf(MSG_ERROR, "Line %d: Too long model_name",
4043 				   line);
4044 			return 1;
4045 		}
4046 		os_free(bss->model_name);
4047 		bss->model_name = os_strdup(pos);
4048 	} else if (os_strcmp(buf, "model_number") == 0) {
4049 		if (os_strlen(pos) > 32) {
4050 			wpa_printf(MSG_ERROR, "Line %d: Too long model_number",
4051 				   line);
4052 			return 1;
4053 		}
4054 		os_free(bss->model_number);
4055 		bss->model_number = os_strdup(pos);
4056 	} else if (os_strcmp(buf, "serial_number") == 0) {
4057 		if (os_strlen(pos) > 32) {
4058 			wpa_printf(MSG_ERROR, "Line %d: Too long serial_number",
4059 				   line);
4060 			return 1;
4061 		}
4062 		os_free(bss->serial_number);
4063 		bss->serial_number = os_strdup(pos);
4064 	} else if (os_strcmp(buf, "device_type") == 0) {
4065 		if (wps_dev_type_str2bin(pos, bss->device_type))
4066 			return 1;
4067 	} else if (os_strcmp(buf, "config_methods") == 0) {
4068 		os_free(bss->config_methods);
4069 		bss->config_methods = os_strdup(pos);
4070 	} else if (os_strcmp(buf, "os_version") == 0) {
4071 		if (hexstr2bin(pos, bss->os_version, 4)) {
4072 			wpa_printf(MSG_ERROR, "Line %d: invalid os_version",
4073 				   line);
4074 			return 1;
4075 		}
4076 	} else if (os_strcmp(buf, "ap_pin") == 0) {
4077 		os_free(bss->ap_pin);
4078 		if (*pos == '\0')
4079 			bss->ap_pin = NULL;
4080 		else
4081 			bss->ap_pin = os_strdup(pos);
4082 	} else if (os_strcmp(buf, "skip_cred_build") == 0) {
4083 		bss->skip_cred_build = atoi(pos);
4084 	} else if (os_strcmp(buf, "extra_cred") == 0) {
4085 		os_free(bss->extra_cred);
4086 		bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len);
4087 		if (bss->extra_cred == NULL) {
4088 			wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'",
4089 				   line, pos);
4090 			return 1;
4091 		}
4092 	} else if (os_strcmp(buf, "wps_cred_processing") == 0) {
4093 		bss->wps_cred_processing = atoi(pos);
4094 	} else if (os_strcmp(buf, "wps_cred_add_sae") == 0) {
4095 		bss->wps_cred_add_sae = atoi(pos);
4096 	} else if (os_strcmp(buf, "ap_settings") == 0) {
4097 		os_free(bss->ap_settings);
4098 		bss->ap_settings =
4099 			(u8 *) os_readfile(pos, &bss->ap_settings_len);
4100 		if (bss->ap_settings == NULL) {
4101 			wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'",
4102 				   line, pos);
4103 			return 1;
4104 		}
4105 	} else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) {
4106 		size_t slen;
4107 		char *str = wpa_config_parse_string(pos, &slen);
4108 
4109 		if (!str || slen < 1 || slen > SSID_MAX_LEN) {
4110 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
4111 				   line, anonymize_ssid(pos));
4112 			os_free(str);
4113 			return 1;
4114 		}
4115 		os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen);
4116 		bss->multi_ap_backhaul_ssid.ssid_len = slen;
4117 		bss->multi_ap_backhaul_ssid.ssid_set = 1;
4118 		os_free(str);
4119 	} else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) {
4120 		int len = os_strlen(pos);
4121 
4122 		if (len < 8 || len > 63) {
4123 			wpa_printf(MSG_ERROR,
4124 				   "Line %d: invalid WPA passphrase length %d (expected 8..63)",
4125 				   line, len);
4126 			return 1;
4127 		}
4128 		os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
4129 		bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos);
4130 		if (bss->multi_ap_backhaul_ssid.wpa_passphrase) {
4131 			hostapd_config_clear_wpa_psk(
4132 				&bss->multi_ap_backhaul_ssid.wpa_psk);
4133 			bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1;
4134 		}
4135 	} else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) {
4136 		hostapd_config_clear_wpa_psk(
4137 			&bss->multi_ap_backhaul_ssid.wpa_psk);
4138 		bss->multi_ap_backhaul_ssid.wpa_psk =
4139 			os_zalloc(sizeof(struct hostapd_wpa_psk));
4140 		if (!bss->multi_ap_backhaul_ssid.wpa_psk)
4141 			return 1;
4142 		if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk,
4143 			       PMK_LEN) ||
4144 		    pos[PMK_LEN * 2] != '\0') {
4145 			wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
4146 				   line, pos);
4147 			hostapd_config_clear_wpa_psk(
4148 				&bss->multi_ap_backhaul_ssid.wpa_psk);
4149 			return 1;
4150 		}
4151 		bss->multi_ap_backhaul_ssid.wpa_psk->group = 1;
4152 		os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
4153 		bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL;
4154 		bss->multi_ap_backhaul_ssid.wpa_psk_set = 1;
4155 	} else if (os_strcmp(buf, "upnp_iface") == 0) {
4156 		os_free(bss->upnp_iface);
4157 		bss->upnp_iface = os_strdup(pos);
4158 	} else if (os_strcmp(buf, "friendly_name") == 0) {
4159 		os_free(bss->friendly_name);
4160 		bss->friendly_name = os_strdup(pos);
4161 	} else if (os_strcmp(buf, "manufacturer_url") == 0) {
4162 		os_free(bss->manufacturer_url);
4163 		bss->manufacturer_url = os_strdup(pos);
4164 	} else if (os_strcmp(buf, "model_description") == 0) {
4165 		os_free(bss->model_description);
4166 		bss->model_description = os_strdup(pos);
4167 	} else if (os_strcmp(buf, "model_url") == 0) {
4168 		os_free(bss->model_url);
4169 		bss->model_url = os_strdup(pos);
4170 	} else if (os_strcmp(buf, "upc") == 0) {
4171 		os_free(bss->upc);
4172 		bss->upc = os_strdup(pos);
4173 	} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
4174 		bss->pbc_in_m1 = atoi(pos);
4175 	} else if (os_strcmp(buf, "server_id") == 0) {
4176 		os_free(bss->server_id);
4177 		bss->server_id = os_strdup(pos);
4178 	} else if (os_strcmp(buf, "wps_application_ext") == 0) {
4179 		wpabuf_free(bss->wps_application_ext);
4180 		bss->wps_application_ext = wpabuf_parse_bin(pos);
4181 #ifdef CONFIG_WPS_NFC
4182 	} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
4183 		bss->wps_nfc_dev_pw_id = atoi(pos);
4184 		if (bss->wps_nfc_dev_pw_id < 0x10 ||
4185 		    bss->wps_nfc_dev_pw_id > 0xffff) {
4186 			wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value",
4187 				   line);
4188 			return 1;
4189 		}
4190 		bss->wps_nfc_pw_from_config = 1;
4191 	} else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
4192 		wpabuf_free(bss->wps_nfc_dh_pubkey);
4193 		bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos);
4194 		bss->wps_nfc_pw_from_config = 1;
4195 	} else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
4196 		wpabuf_free(bss->wps_nfc_dh_privkey);
4197 		bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos);
4198 		bss->wps_nfc_pw_from_config = 1;
4199 	} else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
4200 		wpabuf_free(bss->wps_nfc_dev_pw);
4201 		bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos);
4202 		bss->wps_nfc_pw_from_config = 1;
4203 #endif /* CONFIG_WPS_NFC */
4204 #endif /* CONFIG_WPS */
4205 #ifdef CONFIG_P2P_MANAGER
4206 	} else if (os_strcmp(buf, "manage_p2p") == 0) {
4207 		if (atoi(pos))
4208 			bss->p2p |= P2P_MANAGE;
4209 		else
4210 			bss->p2p &= ~P2P_MANAGE;
4211 	} else if (os_strcmp(buf, "allow_cross_connection") == 0) {
4212 		if (atoi(pos))
4213 			bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
4214 		else
4215 			bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
4216 #endif /* CONFIG_P2P_MANAGER */
4217 	} else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
4218 		bss->disassoc_low_ack = atoi(pos);
4219 	} else if (os_strcmp(buf, "tdls_prohibit") == 0) {
4220 		if (atoi(pos))
4221 			bss->tdls |= TDLS_PROHIBIT;
4222 		else
4223 			bss->tdls &= ~TDLS_PROHIBIT;
4224 	} else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
4225 		if (atoi(pos))
4226 			bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
4227 		else
4228 			bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
4229 #ifdef CONFIG_RSN_TESTING
4230 	} else if (os_strcmp(buf, "rsn_testing") == 0) {
4231 		extern int rsn_testing;
4232 		rsn_testing = atoi(pos);
4233 #endif /* CONFIG_RSN_TESTING */
4234 	} else if (os_strcmp(buf, "time_advertisement") == 0) {
4235 		bss->time_advertisement = atoi(pos);
4236 	} else if (os_strcmp(buf, "time_zone") == 0) {
4237 		size_t tz_len = os_strlen(pos);
4238 		if (tz_len < 4 || tz_len > 255) {
4239 			wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone",
4240 				   line);
4241 			return 1;
4242 		}
4243 		os_free(bss->time_zone);
4244 		bss->time_zone = os_strdup(pos);
4245 		if (bss->time_zone == NULL)
4246 			return 1;
4247 #ifdef CONFIG_WNM_AP
4248 	} else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
4249 		bss->wnm_sleep_mode = atoi(pos);
4250 	} else if (os_strcmp(buf, "wnm_sleep_mode_no_keys") == 0) {
4251 		bss->wnm_sleep_mode_no_keys = atoi(pos);
4252 	} else if (os_strcmp(buf, "bss_transition") == 0) {
4253 		bss->bss_transition = atoi(pos);
4254 #endif /* CONFIG_WNM_AP */
4255 #ifdef CONFIG_INTERWORKING
4256 	} else if (os_strcmp(buf, "interworking") == 0) {
4257 		bss->interworking = atoi(pos);
4258 	} else if (os_strcmp(buf, "access_network_type") == 0) {
4259 		bss->access_network_type = atoi(pos);
4260 		if (bss->access_network_type < 0 ||
4261 		    bss->access_network_type > 15) {
4262 			wpa_printf(MSG_ERROR,
4263 				   "Line %d: invalid access_network_type",
4264 				   line);
4265 			return 1;
4266 		}
4267 	} else if (os_strcmp(buf, "internet") == 0) {
4268 		bss->internet = atoi(pos);
4269 	} else if (os_strcmp(buf, "asra") == 0) {
4270 		bss->asra = atoi(pos);
4271 	} else if (os_strcmp(buf, "esr") == 0) {
4272 		bss->esr = atoi(pos);
4273 	} else if (os_strcmp(buf, "uesa") == 0) {
4274 		bss->uesa = atoi(pos);
4275 	} else if (os_strcmp(buf, "venue_group") == 0) {
4276 		bss->venue_group = atoi(pos);
4277 		bss->venue_info_set = 1;
4278 	} else if (os_strcmp(buf, "venue_type") == 0) {
4279 		bss->venue_type = atoi(pos);
4280 		bss->venue_info_set = 1;
4281 	} else if (os_strcmp(buf, "hessid") == 0) {
4282 		if (hwaddr_aton(pos, bss->hessid)) {
4283 			wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line);
4284 			return 1;
4285 		}
4286 	} else if (os_strcmp(buf, "roaming_consortium") == 0) {
4287 		if (parse_roaming_consortium(bss, pos, line) < 0)
4288 			return 1;
4289 	} else if (os_strcmp(buf, "venue_name") == 0) {
4290 		if (parse_venue_name(bss, pos, line) < 0)
4291 			return 1;
4292 	} else if (os_strcmp(buf, "venue_url") == 0) {
4293 		if (parse_venue_url(bss, pos, line) < 0)
4294 			return 1;
4295 	} else if (os_strcmp(buf, "network_auth_type") == 0) {
4296 		u8 auth_type;
4297 		u16 redirect_url_len;
4298 		if (hexstr2bin(pos, &auth_type, 1)) {
4299 			wpa_printf(MSG_ERROR,
4300 				   "Line %d: Invalid network_auth_type '%s'",
4301 				   line, pos);
4302 			return 1;
4303 		}
4304 		if (auth_type == 0 || auth_type == 2)
4305 			redirect_url_len = os_strlen(pos + 2);
4306 		else
4307 			redirect_url_len = 0;
4308 		os_free(bss->network_auth_type);
4309 		bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1);
4310 		if (bss->network_auth_type == NULL)
4311 			return 1;
4312 		*bss->network_auth_type = auth_type;
4313 		WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len);
4314 		if (redirect_url_len)
4315 			os_memcpy(bss->network_auth_type + 3, pos + 2,
4316 				  redirect_url_len);
4317 		bss->network_auth_type_len = 3 + redirect_url_len;
4318 	} else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
4319 		if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) {
4320 			wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'",
4321 				   line, anonymize_common(pos));
4322 			bss->ipaddr_type_configured = 0;
4323 			return 1;
4324 		}
4325 		bss->ipaddr_type_configured = 1;
4326 	} else if (os_strcmp(buf, "domain_name") == 0) {
4327 		int j, num_domains, domain_len, domain_list_len = 0;
4328 		char *tok_start, *tok_prev;
4329 		u8 *domain_list, *domain_ptr;
4330 
4331 		domain_list_len = os_strlen(pos) + 1;
4332 		domain_list = os_malloc(domain_list_len);
4333 		if (domain_list == NULL)
4334 			return 1;
4335 
4336 		domain_ptr = domain_list;
4337 		tok_prev = pos;
4338 		num_domains = 1;
4339 		while ((tok_prev = os_strchr(tok_prev, ','))) {
4340 			num_domains++;
4341 			tok_prev++;
4342 		}
4343 		tok_prev = pos;
4344 		for (j = 0; j < num_domains; j++) {
4345 			tok_start = os_strchr(tok_prev, ',');
4346 			if (tok_start) {
4347 				domain_len = tok_start - tok_prev;
4348 				*domain_ptr = domain_len;
4349 				os_memcpy(domain_ptr + 1, tok_prev, domain_len);
4350 				domain_ptr += domain_len + 1;
4351 				tok_prev = ++tok_start;
4352 			} else {
4353 				domain_len = os_strlen(tok_prev);
4354 				*domain_ptr = domain_len;
4355 				os_memcpy(domain_ptr + 1, tok_prev, domain_len);
4356 				domain_ptr += domain_len + 1;
4357 			}
4358 		}
4359 
4360 		os_free(bss->domain_name);
4361 		bss->domain_name = domain_list;
4362 		bss->domain_name_len = domain_list_len;
4363 	} else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
4364 		if (parse_3gpp_cell_net(bss, pos, line) < 0)
4365 			return 1;
4366 	} else if (os_strcmp(buf, "nai_realm") == 0) {
4367 		if (parse_nai_realm(bss, pos, line) < 0)
4368 			return 1;
4369 	} else if (os_strcmp(buf, "anqp_elem") == 0) {
4370 		if (parse_anqp_elem(bss, pos, line) < 0)
4371 			return 1;
4372 	} else if (os_strcmp(buf, "gas_frag_limit") == 0) {
4373 		int val = atoi(pos);
4374 
4375 		if (val <= 0) {
4376 			wpa_printf(MSG_ERROR,
4377 				   "Line %d: Invalid gas_frag_limit '%s'",
4378 				   line, pos);
4379 			return 1;
4380 		}
4381 		bss->gas_frag_limit = val;
4382 	} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
4383 		bss->gas_comeback_delay = atoi(pos);
4384 #endif /* CONFIG_INTERWORKING */
4385 	} else if (os_strcmp(buf, "qos_map_set") == 0) {
4386 		if (parse_qos_map_set(bss, pos, line) < 0)
4387 			return 1;
4388 #ifdef CONFIG_RADIUS_TEST
4389 	} else if (os_strcmp(buf, "dump_msk_file") == 0) {
4390 		os_free(bss->dump_msk_file);
4391 		bss->dump_msk_file = os_strdup(pos);
4392 #endif /* CONFIG_RADIUS_TEST */
4393 #ifdef CONFIG_PROXYARP
4394 	} else if (os_strcmp(buf, "proxy_arp") == 0) {
4395 		bss->proxy_arp = atoi(pos);
4396 #endif /* CONFIG_PROXYARP */
4397 #ifdef CONFIG_HS20
4398 	} else if (os_strcmp(buf, "hs20") == 0) {
4399 		bss->hs20 = atoi(pos);
4400 	} else if (os_strcmp(buf, "hs20_release") == 0) {
4401 		int val = atoi(pos);
4402 
4403 		if (val < 1 || val > (HS20_VERSION >> 4) + 1) {
4404 			wpa_printf(MSG_ERROR,
4405 				   "Line %d: Unsupported hs20_release: %s",
4406 				   line, pos);
4407 			return 1;
4408 		}
4409 		bss->hs20_release = val;
4410 	} else if (os_strcmp(buf, "disable_dgaf") == 0) {
4411 		bss->disable_dgaf = atoi(pos);
4412 	} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
4413 		bss->na_mcast_to_ucast = atoi(pos);
4414 	} else if (os_strcmp(buf, "osen") == 0) {
4415 		bss->osen = atoi(pos);
4416 	} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
4417 		bss->anqp_domain_id = atoi(pos);
4418 	} else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
4419 		bss->hs20_deauth_req_timeout = atoi(pos);
4420 	} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
4421 		if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
4422 			return 1;
4423 	} else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
4424 		if (hs20_parse_wan_metrics(bss, pos, line) < 0)
4425 			return 1;
4426 	} else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
4427 		if (hs20_parse_conn_capab(bss, pos, line) < 0) {
4428 			return 1;
4429 		}
4430 	} else if (os_strcmp(buf, "hs20_operating_class") == 0) {
4431 		u8 *oper_class;
4432 		size_t oper_class_len;
4433 		oper_class_len = os_strlen(pos);
4434 		if (oper_class_len < 2 || (oper_class_len & 0x01)) {
4435 			wpa_printf(MSG_ERROR,
4436 				   "Line %d: Invalid hs20_operating_class '%s'",
4437 				   line, pos);
4438 			return 1;
4439 		}
4440 		oper_class_len /= 2;
4441 		oper_class = os_malloc(oper_class_len);
4442 		if (oper_class == NULL)
4443 			return 1;
4444 		if (hexstr2bin(pos, oper_class, oper_class_len)) {
4445 			wpa_printf(MSG_ERROR,
4446 				   "Line %d: Invalid hs20_operating_class '%s'",
4447 				   line, pos);
4448 			os_free(oper_class);
4449 			return 1;
4450 		}
4451 		os_free(bss->hs20_operating_class);
4452 		bss->hs20_operating_class = oper_class;
4453 		bss->hs20_operating_class_len = oper_class_len;
4454 	} else if (os_strcmp(buf, "hs20_icon") == 0) {
4455 		if (hs20_parse_icon(bss, pos) < 0) {
4456 			wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
4457 				   line, pos);
4458 			return 1;
4459 		}
4460 	} else if (os_strcmp(buf, "osu_ssid") == 0) {
4461 		if (hs20_parse_osu_ssid(bss, pos, line) < 0)
4462 			return 1;
4463 	} else if (os_strcmp(buf, "osu_server_uri") == 0) {
4464 		if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
4465 			return 1;
4466 	} else if (os_strcmp(buf, "osu_friendly_name") == 0) {
4467 		if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
4468 			return 1;
4469 	} else if (os_strcmp(buf, "osu_nai") == 0) {
4470 		if (hs20_parse_osu_nai(bss, pos, line) < 0)
4471 			return 1;
4472 	} else if (os_strcmp(buf, "osu_nai2") == 0) {
4473 		if (hs20_parse_osu_nai2(bss, pos, line) < 0)
4474 			return 1;
4475 	} else if (os_strcmp(buf, "osu_method_list") == 0) {
4476 		if (hs20_parse_osu_method_list(bss, pos, line) < 0)
4477 			return 1;
4478 	} else if (os_strcmp(buf, "osu_icon") == 0) {
4479 		if (hs20_parse_osu_icon(bss, pos, line) < 0)
4480 			return 1;
4481 	} else if (os_strcmp(buf, "osu_service_desc") == 0) {
4482 		if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
4483 			return 1;
4484 	} else if (os_strcmp(buf, "operator_icon") == 0) {
4485 		if (hs20_parse_operator_icon(bss, pos, line) < 0)
4486 			return 1;
4487 	} else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
4488 		os_free(bss->subscr_remediation_url);
4489 		bss->subscr_remediation_url = os_strdup(pos);
4490 	} else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
4491 		bss->subscr_remediation_method = atoi(pos);
4492 	} else if (os_strcmp(buf, "hs20_t_c_filename") == 0) {
4493 		os_free(bss->t_c_filename);
4494 		bss->t_c_filename = os_strdup(pos);
4495 	} else if (os_strcmp(buf, "hs20_t_c_timestamp") == 0) {
4496 		bss->t_c_timestamp = strtol(pos, NULL, 0);
4497 	} else if (os_strcmp(buf, "hs20_t_c_server_url") == 0) {
4498 		os_free(bss->t_c_server_url);
4499 		bss->t_c_server_url = os_strdup(pos);
4500 	} else if (os_strcmp(buf, "hs20_sim_provisioning_url") == 0) {
4501 		os_free(bss->hs20_sim_provisioning_url);
4502 		bss->hs20_sim_provisioning_url = os_strdup(pos);
4503 #endif /* CONFIG_HS20 */
4504 #ifdef CONFIG_MBO
4505 	} else if (os_strcmp(buf, "mbo") == 0) {
4506 		bss->mbo_enabled = atoi(pos);
4507 	} else if (os_strcmp(buf, "mbo_cell_data_conn_pref") == 0) {
4508 		bss->mbo_cell_data_conn_pref = atoi(pos);
4509 	} else if (os_strcmp(buf, "oce") == 0) {
4510 		bss->oce = atoi(pos);
4511 #endif /* CONFIG_MBO */
4512 #ifdef CONFIG_TESTING_OPTIONS
4513 #define PARSE_TEST_PROBABILITY(_val)				\
4514 	} else if (os_strcmp(buf, #_val) == 0) {		\
4515 		char *end;					\
4516 								\
4517 		conf->_val = strtod(pos, &end);			\
4518 		if (*end || conf->_val < 0.0 ||			\
4519 		    conf->_val > 1.0) {				\
4520 			wpa_printf(MSG_ERROR,			\
4521 				   "Line %d: Invalid value '%s'", \
4522 				   line, pos);			\
4523 			return 1;				\
4524 		}
4525 	PARSE_TEST_PROBABILITY(ignore_probe_probability)
4526 	PARSE_TEST_PROBABILITY(ignore_auth_probability)
4527 	PARSE_TEST_PROBABILITY(ignore_assoc_probability)
4528 	PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
4529 	PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
4530 	} else if (os_strcmp(buf, "ecsa_ie_only") == 0) {
4531 		conf->ecsa_ie_only = atoi(pos);
4532 	} else if (os_strcmp(buf, "bss_load_test") == 0) {
4533 		WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
4534 		pos = os_strchr(pos, ':');
4535 		if (pos == NULL) {
4536 			wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
4537 				   line);
4538 			return 1;
4539 		}
4540 		pos++;
4541 		bss->bss_load_test[2] = atoi(pos);
4542 		pos = os_strchr(pos, ':');
4543 		if (pos == NULL) {
4544 			wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
4545 				   line);
4546 			return 1;
4547 		}
4548 		pos++;
4549 		WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
4550 		bss->bss_load_test_set = 1;
4551 	} else if (os_strcmp(buf, "radio_measurements") == 0) {
4552 		/*
4553 		 * DEPRECATED: This parameter will be removed in the future.
4554 		 * Use rrm_neighbor_report instead.
4555 		 */
4556 		int val = atoi(pos);
4557 
4558 		if (val & BIT(0))
4559 			bss->radio_measurements[0] |=
4560 				WLAN_RRM_CAPS_NEIGHBOR_REPORT;
4561 	} else if (os_strcmp(buf, "own_ie_override") == 0) {
4562 		struct wpabuf *tmp;
4563 		size_t len = os_strlen(pos) / 2;
4564 
4565 		tmp = wpabuf_alloc(len);
4566 		if (!tmp)
4567 			return 1;
4568 
4569 		if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
4570 			wpabuf_free(tmp);
4571 			wpa_printf(MSG_ERROR,
4572 				   "Line %d: Invalid own_ie_override '%s'",
4573 				   line, pos);
4574 			return 1;
4575 		}
4576 
4577 		wpabuf_free(bss->own_ie_override);
4578 		bss->own_ie_override = tmp;
4579 	} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
4580 		bss->sae_reflection_attack = atoi(pos);
4581 	} else if (os_strcmp(buf, "sae_commit_status") == 0) {
4582 		bss->sae_commit_status = atoi(pos);
4583 	} else if (os_strcmp(buf, "sae_pk_omit") == 0) {
4584 		bss->sae_pk_omit = atoi(pos);
4585 	} else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) {
4586 		bss->sae_pk_password_check_skip = atoi(pos);
4587 	} else if (os_strcmp(buf, "sae_commit_override") == 0) {
4588 		wpabuf_free(bss->sae_commit_override);
4589 		bss->sae_commit_override = wpabuf_parse_bin(pos);
4590 	} else if (os_strcmp(buf, "rsne_override_eapol") == 0) {
4591 		wpabuf_free(bss->rsne_override_eapol);
4592 		bss->rsne_override_eapol = wpabuf_parse_bin(pos);
4593 	} else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
4594 		wpabuf_free(bss->rsnxe_override_eapol);
4595 		bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
4596 	} else if (os_strcmp(buf, "rsne_override_ft") == 0) {
4597 		wpabuf_free(bss->rsne_override_ft);
4598 		bss->rsne_override_ft = wpabuf_parse_bin(pos);
4599 	} else if (os_strcmp(buf, "rsnxe_override_ft") == 0) {
4600 		wpabuf_free(bss->rsnxe_override_ft);
4601 		bss->rsnxe_override_ft = wpabuf_parse_bin(pos);
4602 	} else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
4603 		wpabuf_free(bss->gtk_rsc_override);
4604 		bss->gtk_rsc_override = wpabuf_parse_bin(pos);
4605 	} else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
4606 		wpabuf_free(bss->igtk_rsc_override);
4607 		bss->igtk_rsc_override = wpabuf_parse_bin(pos);
4608 	} else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) {
4609 		bss->no_beacon_rsnxe = atoi(pos);
4610 	} else if (os_strcmp(buf, "skip_prune_assoc") == 0) {
4611 		bss->skip_prune_assoc = atoi(pos);
4612 	} else if (os_strcmp(buf, "ft_rsnxe_used") == 0) {
4613 		bss->ft_rsnxe_used = atoi(pos);
4614 	} else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) {
4615 		bss->oci_freq_override_eapol_m3 = atoi(pos);
4616 	} else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) {
4617 		bss->oci_freq_override_eapol_g1 = atoi(pos);
4618 	} else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) {
4619 		bss->oci_freq_override_saquery_req = atoi(pos);
4620 	} else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) {
4621 		bss->oci_freq_override_saquery_resp = atoi(pos);
4622 	} else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) {
4623 		bss->oci_freq_override_ft_assoc = atoi(pos);
4624 	} else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) {
4625 		bss->oci_freq_override_fils_assoc = atoi(pos);
4626 	} else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
4627 		bss->oci_freq_override_wnm_sleep = atoi(pos);
4628 	} else if (os_strcmp(buf, "eap_skip_prot_success") == 0) {
4629 		bss->eap_skip_prot_success = atoi(pos);
4630 	} else if (os_strcmp(buf, "delay_eapol_tx") == 0) {
4631 		conf->delay_eapol_tx = atoi(pos);
4632 	} else if (os_strcmp(buf, "eapol_m1_elements") == 0) {
4633 		if (parse_wpabuf_hex(line, buf, &bss->eapol_m1_elements, pos))
4634 			return 1;
4635 	} else if (os_strcmp(buf, "eapol_m3_elements") == 0) {
4636 		if (parse_wpabuf_hex(line, buf, &bss->eapol_m3_elements, pos))
4637 			return 1;
4638 	} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
4639 		bss->eapol_m3_no_encrypt = atoi(pos);
4640 	} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
4641 		bss->test_assoc_comeback_type = atoi(pos);
4642 	} else if (os_strcmp(buf, "presp_elements") == 0) {
4643 		if (parse_wpabuf_hex(line, buf, &bss->presp_elements, pos))
4644 			return 1;
4645 #endif /* CONFIG_TESTING_OPTIONS */
4646 #ifdef CONFIG_SAE
4647 	} else if (os_strcmp(buf, "sae_password") == 0) {
4648 		if (parse_sae_password(bss, pos) < 0) {
4649 			wpa_printf(MSG_ERROR, "Line %d: Invalid sae_password",
4650 				   line);
4651 			return 1;
4652 		}
4653 	} else if (os_strcmp(buf, "sae_password_file") == 0) {
4654 		if (parse_sae_password_file(bss, pos) < 0) {
4655 			wpa_printf(MSG_ERROR,
4656 				   "Line %d: Invalid sae_password in file",
4657 				   line);
4658 			return 1;
4659 		}
4660 #endif /* CONFIG_SAE */
4661 	} else if (os_strcmp(buf, "vendor_elements") == 0) {
4662 		if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
4663 			return 1;
4664 	} else if (os_strcmp(buf, "assocresp_elements") == 0) {
4665 		if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
4666 			return 1;
4667 	} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0 ||
4668 		   os_strcmp(buf, "anti_clogging_threshold") == 0) {
4669 		bss->anti_clogging_threshold = atoi(pos);
4670 	} else if (os_strcmp(buf, "sae_sync") == 0) {
4671 		bss->sae_sync = atoi(pos);
4672 	} else if (os_strcmp(buf, "sae_groups") == 0) {
4673 		if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
4674 			wpa_printf(MSG_ERROR,
4675 				   "Line %d: Invalid sae_groups value '%s'",
4676 				   line, pos);
4677 			return 1;
4678 		}
4679 	} else if (os_strcmp(buf, "sae_require_mfp") == 0) {
4680 		bss->sae_require_mfp = atoi(pos);
4681 	} else if (os_strcmp(buf, "sae_confirm_immediate") == 0) {
4682 		bss->sae_confirm_immediate = atoi(pos);
4683 	} else if (os_strcmp(buf, "sae_pwe") == 0) {
4684 		bss->sae_pwe = atoi(pos);
4685 	} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
4686 		int val = atoi(pos);
4687 		if (val < 0 || val > 255) {
4688 			wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
4689 				   line, val);
4690 			return 1;
4691 		}
4692 		conf->local_pwr_constraint = val;
4693 	} else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
4694 		conf->spectrum_mgmt_required = atoi(pos);
4695 	} else if (os_strcmp(buf, "wowlan_triggers") == 0) {
4696 		os_free(bss->wowlan_triggers);
4697 		bss->wowlan_triggers = os_strdup(pos);
4698 #ifdef CONFIG_FST
4699 	} else if (os_strcmp(buf, "fst_group_id") == 0) {
4700 		size_t len = os_strlen(pos);
4701 
4702 		if (!len || len >= sizeof(conf->fst_cfg.group_id)) {
4703 			wpa_printf(MSG_ERROR,
4704 				   "Line %d: Invalid fst_group_id value '%s'",
4705 				   line, pos);
4706 			return 1;
4707 		}
4708 
4709 		if (conf->fst_cfg.group_id[0]) {
4710 			wpa_printf(MSG_ERROR,
4711 				   "Line %d: Duplicate fst_group value '%s'",
4712 				   line, pos);
4713 			return 1;
4714 		}
4715 
4716 		os_strlcpy(conf->fst_cfg.group_id, pos,
4717 			   sizeof(conf->fst_cfg.group_id));
4718 	} else if (os_strcmp(buf, "fst_priority") == 0) {
4719 		char *endp;
4720 		long int val;
4721 
4722 		if (!*pos) {
4723 			wpa_printf(MSG_ERROR,
4724 				   "Line %d: fst_priority value not supplied (expected 1..%u)",
4725 				   line, FST_MAX_PRIO_VALUE);
4726 			return -1;
4727 		}
4728 
4729 		val = strtol(pos, &endp, 0);
4730 		if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) {
4731 			wpa_printf(MSG_ERROR,
4732 				   "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)",
4733 				   line, val, pos, FST_MAX_PRIO_VALUE);
4734 			return 1;
4735 		}
4736 		conf->fst_cfg.priority = (u8) val;
4737 	} else if (os_strcmp(buf, "fst_llt") == 0) {
4738 		char *endp;
4739 		long int val;
4740 
4741 		if (!*pos) {
4742 			wpa_printf(MSG_ERROR,
4743 				   "Line %d: fst_llt value not supplied (expected 1..%u)",
4744 				   line, FST_MAX_LLT_MS);
4745 			return -1;
4746 		}
4747 		val = strtol(pos, &endp, 0);
4748 		if (*endp || val < 1 ||
4749 		    (unsigned long int) val > FST_MAX_LLT_MS) {
4750 			wpa_printf(MSG_ERROR,
4751 				   "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
4752 				   line, val, pos, FST_MAX_LLT_MS);
4753 			return 1;
4754 		}
4755 		conf->fst_cfg.llt = (u32) val;
4756 #endif /* CONFIG_FST */
4757 	} else if (os_strcmp(buf, "track_sta_max_num") == 0) {
4758 		conf->track_sta_max_num = atoi(pos);
4759 	} else if (os_strcmp(buf, "track_sta_max_age") == 0) {
4760 		conf->track_sta_max_age = atoi(pos);
4761 	} else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) {
4762 		os_free(bss->no_probe_resp_if_seen_on);
4763 		bss->no_probe_resp_if_seen_on = os_strdup(pos);
4764 	} else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
4765 		os_free(bss->no_auth_if_seen_on);
4766 		bss->no_auth_if_seen_on = os_strdup(pos);
4767 	} else if (os_strcmp(buf, "lci") == 0) {
4768 		wpabuf_free(conf->lci);
4769 		conf->lci = wpabuf_parse_bin(pos);
4770 		if (conf->lci && wpabuf_len(conf->lci) == 0) {
4771 			wpabuf_free(conf->lci);
4772 			conf->lci = NULL;
4773 		}
4774 	} else if (os_strcmp(buf, "civic") == 0) {
4775 		wpabuf_free(conf->civic);
4776 		conf->civic = wpabuf_parse_bin(pos);
4777 		if (conf->civic && wpabuf_len(conf->civic) == 0) {
4778 			wpabuf_free(conf->civic);
4779 			conf->civic = NULL;
4780 		}
4781 	} else if (os_strcmp(buf, "rrm_neighbor_report") == 0) {
4782 		if (atoi(pos))
4783 			bss->radio_measurements[0] |=
4784 				WLAN_RRM_CAPS_NEIGHBOR_REPORT;
4785 	} else if (os_strcmp(buf, "rrm_beacon_report") == 0) {
4786 		if (atoi(pos))
4787 			bss->radio_measurements[0] |=
4788 				WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
4789 				WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
4790 				WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
4791 	} else if (os_strcmp(buf, "rrm_link_measurement_report") == 0) {
4792 		if (atoi(pos))
4793 			bss->radio_measurements[0] |=
4794 				WLAN_RRM_CAPS_LINK_MEASUREMENT;
4795 	} else if (os_strcmp(buf, "gas_address3") == 0) {
4796 		bss->gas_address3 = atoi(pos);
4797 	} else if (os_strcmp(buf, "stationary_ap") == 0) {
4798 		conf->stationary_ap = atoi(pos);
4799 	} else if (os_strcmp(buf, "ftm_responder") == 0) {
4800 		bss->ftm_responder = atoi(pos);
4801 	} else if (os_strcmp(buf, "ftm_initiator") == 0) {
4802 		bss->ftm_initiator = atoi(pos);
4803 #ifdef CONFIG_FILS
4804 	} else if (os_strcmp(buf, "fils_cache_id") == 0) {
4805 		if (hexstr2bin(pos, bss->fils_cache_id, FILS_CACHE_ID_LEN)) {
4806 			wpa_printf(MSG_ERROR,
4807 				   "Line %d: Invalid fils_cache_id '%s'",
4808 				   line, pos);
4809 			return 1;
4810 		}
4811 		bss->fils_cache_id_set = 1;
4812 	} else if (os_strcmp(buf, "fils_realm") == 0) {
4813 		if (parse_fils_realm(bss, pos) < 0)
4814 			return 1;
4815 	} else if (os_strcmp(buf, "fils_dh_group") == 0) {
4816 		bss->fils_dh_group = atoi(pos);
4817 	} else if (os_strcmp(buf, "dhcp_server") == 0) {
4818 		if (hostapd_parse_ip_addr(pos, &bss->dhcp_server)) {
4819 			wpa_printf(MSG_ERROR,
4820 				   "Line %d: invalid IP address '%s'",
4821 				   line, pos);
4822 			return 1;
4823 		}
4824 	} else if (os_strcmp(buf, "dhcp_rapid_commit_proxy") == 0) {
4825 		bss->dhcp_rapid_commit_proxy = atoi(pos);
4826 	} else if (os_strcmp(buf, "fils_hlp_wait_time") == 0) {
4827 		bss->fils_hlp_wait_time = atoi(pos);
4828 	} else if (os_strcmp(buf, "dhcp_server_port") == 0) {
4829 		bss->dhcp_server_port = atoi(pos);
4830 	} else if (os_strcmp(buf, "dhcp_relay_port") == 0) {
4831 		bss->dhcp_relay_port = atoi(pos);
4832 	} else if (os_strcmp(buf, "fils_discovery_min_interval") == 0) {
4833 		bss->fils_discovery_min_int = atoi(pos);
4834 	} else if (os_strcmp(buf, "fils_discovery_max_interval") == 0) {
4835 		bss->fils_discovery_max_int = atoi(pos);
4836 #endif /* CONFIG_FILS */
4837 	} else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
4838 		bss->multicast_to_unicast = atoi(pos);
4839 	} else if (os_strcmp(buf, "bridge_multicast_to_unicast") == 0) {
4840 		bss->bridge_multicast_to_unicast = atoi(pos);
4841 	} else if (os_strcmp(buf, "broadcast_deauth") == 0) {
4842 		bss->broadcast_deauth = atoi(pos);
4843 	} else if (os_strcmp(buf, "notify_mgmt_frames") == 0) {
4844 		bss->notify_mgmt_frames = atoi(pos);
4845 #ifdef CONFIG_DPP
4846 	} else if (os_strcmp(buf, "dpp_name") == 0) {
4847 		os_free(bss->dpp_name);
4848 		bss->dpp_name = os_strdup(pos);
4849 	} else if (os_strcmp(buf, "dpp_mud_url") == 0) {
4850 		os_free(bss->dpp_mud_url);
4851 		bss->dpp_mud_url = os_strdup(pos);
4852 	} else if (os_strcmp(buf, "dpp_extra_conf_req_name") == 0) {
4853 		os_free(bss->dpp_extra_conf_req_name);
4854 		bss->dpp_extra_conf_req_name = os_strdup(pos);
4855 	} else if (os_strcmp(buf, "dpp_extra_conf_req_value") == 0) {
4856 		os_free(bss->dpp_extra_conf_req_value);
4857 		bss->dpp_extra_conf_req_value = os_strdup(pos);
4858 	} else if (os_strcmp(buf, "dpp_connector") == 0) {
4859 		os_free(bss->dpp_connector);
4860 		bss->dpp_connector = os_strdup(pos);
4861 	} else if (os_strcmp(buf, "dpp_netaccesskey") == 0) {
4862 		if (parse_wpabuf_hex(line, buf, &bss->dpp_netaccesskey, pos))
4863 			return 1;
4864 	} else if (os_strcmp(buf, "dpp_netaccesskey_expiry") == 0) {
4865 		bss->dpp_netaccesskey_expiry = strtol(pos, NULL, 0);
4866 	} else if (os_strcmp(buf, "dpp_csign") == 0) {
4867 		if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos))
4868 			return 1;
4869 #ifdef CONFIG_DPP2
4870 	} else if (os_strcmp(buf, "dpp_controller") == 0) {
4871 		if (hostapd_dpp_controller_parse(bss, pos))
4872 			return 1;
4873 	} else if (os_strcmp(buf, "dpp_relay_port") == 0) {
4874 		bss->dpp_relay_port = atoi(pos);
4875 	} else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) {
4876 		bss->dpp_configurator_connectivity = atoi(pos);
4877 	} else if (os_strcmp(buf, "dpp_pfs") == 0) {
4878 		int val = atoi(pos);
4879 
4880 		if (val < 0 || val > 2) {
4881 			wpa_printf(MSG_ERROR,
4882 				   "Line %d: Invalid dpp_pfs value '%s'",
4883 				   line, pos);
4884 			return -1;
4885 		}
4886 		bss->dpp_pfs = val;
4887 #endif /* CONFIG_DPP2 */
4888 #endif /* CONFIG_DPP */
4889 #ifdef CONFIG_OWE
4890 	} else if (os_strcmp(buf, "owe_transition_bssid") == 0) {
4891 		if (hwaddr_aton(pos, bss->owe_transition_bssid)) {
4892 			wpa_printf(MSG_ERROR,
4893 				   "Line %d: invalid owe_transition_bssid",
4894 				   line);
4895 			return 1;
4896 		}
4897 	} else if (os_strcmp(buf, "owe_transition_ssid") == 0) {
4898 		size_t slen;
4899 		char *str = wpa_config_parse_string(pos, &slen);
4900 
4901 		if (!str || slen < 1 || slen > SSID_MAX_LEN) {
4902 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
4903 				   line, anonymize_ssid(pos));
4904 			os_free(str);
4905 			return 1;
4906 		}
4907 		os_memcpy(bss->owe_transition_ssid, str, slen);
4908 		bss->owe_transition_ssid_len = slen;
4909 		os_free(str);
4910 	} else if (os_strcmp(buf, "owe_transition_ifname") == 0) {
4911 		os_strlcpy(bss->owe_transition_ifname, pos,
4912 			   sizeof(bss->owe_transition_ifname));
4913 	} else if (os_strcmp(buf, "owe_groups") == 0) {
4914 		if (hostapd_parse_intlist(&bss->owe_groups, pos)) {
4915 			wpa_printf(MSG_ERROR,
4916 				   "Line %d: Invalid owe_groups value '%s'",
4917 				   line, pos);
4918 			return 1;
4919 		}
4920 	} else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
4921 		bss->owe_ptk_workaround = atoi(pos);
4922 #endif /* CONFIG_OWE */
4923 	} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
4924 		bss->coloc_intf_reporting = atoi(pos);
4925 	} else if (os_strcmp(buf, "multi_ap") == 0) {
4926 		int val = atoi(pos);
4927 
4928 		if (val < 0 || val > 3) {
4929 			wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'",
4930 				   line, buf);
4931 			return -1;
4932 		}
4933 
4934 		bss->multi_ap = val;
4935 	} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
4936 		int val = atoi(pos);
4937 
4938 		if (val < MULTI_AP_PROFILE_1 || val > MULTI_AP_PROFILE_MAX) {
4939 			wpa_printf(MSG_ERROR,
4940 				   "Line %d: Invalid multi_ap_profile '%s'",
4941 				   line, buf);
4942 			return -1;
4943 		}
4944 		bss->multi_ap_profile = val;
4945 	} else if (os_strcmp(buf, "multi_ap_client_disallow") == 0) {
4946 		int val = atoi(pos);
4947 
4948 		if (val < 0 || val > 3) {
4949 			wpa_printf(MSG_ERROR,
4950 				   "Line %d: Invalid multi_ap_client_allow '%s'",
4951 				   line, buf);
4952 			return -1;
4953 		}
4954 		bss->multi_ap_client_disallow = val;
4955 	} else if (os_strcmp(buf, "multi_ap_vlanid") == 0) {
4956 		int val = atoi(pos);
4957 
4958 		if (val < 0 || val > MAX_VLAN_ID) {
4959 			wpa_printf(MSG_ERROR,
4960 				   "Line %d: Invalid multi_ap_vlan_id '%s'",
4961 				   line, buf);
4962 			return -1;
4963 		}
4964 		bss->multi_ap_vlanid = val;
4965 	} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
4966 		conf->rssi_reject_assoc_rssi = atoi(pos);
4967 	} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
4968 		conf->rssi_reject_assoc_timeout = atoi(pos);
4969 	} else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) {
4970 		conf->rssi_ignore_probe_request = atoi(pos);
4971 	} else if (os_strcmp(buf, "pbss") == 0) {
4972 		bss->pbss = atoi(pos);
4973 	} else if (os_strcmp(buf, "transition_disable") == 0) {
4974 		bss->transition_disable = strtol(pos, NULL, 16);
4975 #ifdef CONFIG_AIRTIME_POLICY
4976 	} else if (os_strcmp(buf, "airtime_mode") == 0) {
4977 		int val = atoi(pos);
4978 
4979 		if (val < 0 || val > AIRTIME_MODE_MAX) {
4980 			wpa_printf(MSG_ERROR, "Line %d: Unknown airtime_mode",
4981 				   line);
4982 			return 1;
4983 		}
4984 		conf->airtime_mode = val;
4985 	} else if (os_strcmp(buf, "airtime_update_interval") == 0) {
4986 		conf->airtime_update_interval = atoi(pos);
4987 	} else if (os_strcmp(buf, "airtime_bss_weight") == 0) {
4988 		bss->airtime_weight = atoi(pos);
4989 	} else if (os_strcmp(buf, "airtime_bss_limit") == 0) {
4990 		int val = atoi(pos);
4991 
4992 		if (val < 0 || val > 1) {
4993 			wpa_printf(MSG_ERROR,
4994 				   "Line %d: Invalid airtime_bss_limit (must be 0 or 1)",
4995 				   line);
4996 			return 1;
4997 		}
4998 		bss->airtime_limit = val;
4999 	} else if (os_strcmp(buf, "airtime_sta_weight") == 0) {
5000 		if (add_airtime_weight(bss, pos) < 0) {
5001 			wpa_printf(MSG_ERROR,
5002 				   "Line %d: Invalid airtime weight '%s'",
5003 				   line, pos);
5004 			return 1;
5005 		}
5006 #endif /* CONFIG_AIRTIME_POLICY */
5007 #ifdef CONFIG_MACSEC
5008 	} else if (os_strcmp(buf, "macsec_policy") == 0) {
5009 		int macsec_policy = atoi(pos);
5010 
5011 		if (macsec_policy < 0 || macsec_policy > 1) {
5012 			wpa_printf(MSG_ERROR,
5013 				   "Line %d: invalid macsec_policy (%d): '%s'.",
5014 				   line, macsec_policy, pos);
5015 			return 1;
5016 		}
5017 		bss->macsec_policy = macsec_policy;
5018 	} else if (os_strcmp(buf, "macsec_integ_only") == 0) {
5019 		int macsec_integ_only = atoi(pos);
5020 
5021 		if (macsec_integ_only < 0 || macsec_integ_only > 1) {
5022 			wpa_printf(MSG_ERROR,
5023 				   "Line %d: invalid macsec_integ_only (%d): '%s'.",
5024 				   line, macsec_integ_only, pos);
5025 			return 1;
5026 		}
5027 		bss->macsec_integ_only = macsec_integ_only;
5028 	} else if (os_strcmp(buf, "macsec_replay_protect") == 0) {
5029 		int macsec_replay_protect = atoi(pos);
5030 
5031 		if (macsec_replay_protect < 0 || macsec_replay_protect > 1) {
5032 			wpa_printf(MSG_ERROR,
5033 				   "Line %d: invalid macsec_replay_protect (%d): '%s'.",
5034 				   line, macsec_replay_protect, pos);
5035 			return 1;
5036 		}
5037 		bss->macsec_replay_protect = macsec_replay_protect;
5038 	} else if (os_strcmp(buf, "macsec_replay_window") == 0) {
5039 		bss->macsec_replay_window = atoi(pos);
5040 	} else if (os_strcmp(buf, "macsec_offload") == 0) {
5041 		int macsec_offload = atoi(pos);
5042 
5043 		if (macsec_offload < 0 || macsec_offload > 2) {
5044 			wpa_printf(MSG_ERROR,
5045 				   "Line %d: invalid macsec_offload (%d): '%s'.",
5046 				   line, macsec_offload, pos);
5047 			return 1;
5048 		}
5049 		bss->macsec_offload = macsec_offload;
5050 	} else if (os_strcmp(buf, "macsec_port") == 0) {
5051 		int macsec_port = atoi(pos);
5052 
5053 		if (macsec_port < 1 || macsec_port > 65534) {
5054 			wpa_printf(MSG_ERROR,
5055 				   "Line %d: invalid macsec_port (%d): '%s'.",
5056 				   line, macsec_port, pos);
5057 			return 1;
5058 		}
5059 		bss->macsec_port = macsec_port;
5060 	} else if (os_strcmp(buf, "mka_priority") == 0) {
5061 		int mka_priority = atoi(pos);
5062 
5063 		if (mka_priority < 0 || mka_priority > 255) {
5064 			wpa_printf(MSG_ERROR,
5065 				   "Line %d: invalid mka_priority (%d): '%s'.",
5066 				   line, mka_priority, pos);
5067 			return 1;
5068 		}
5069 		bss->mka_priority = mka_priority;
5070 	} else if (os_strcmp(buf, "macsec_csindex") == 0) {
5071 		int macsec_csindex = atoi(pos);
5072 
5073 		if (macsec_csindex < 0 || macsec_csindex > 1) {
5074 			wpa_printf(MSG_ERROR,
5075 				   "Line %d: invalid macsec_csindex (%d): '%s'.",
5076 				   line, macsec_csindex, pos);
5077 			return 1;
5078 		}
5079 		bss->macsec_csindex = macsec_csindex;
5080 	} else if (os_strcmp(buf, "mka_cak") == 0) {
5081 		size_t len = os_strlen(pos);
5082 
5083 		if (len > 2 * MACSEC_CAK_MAX_LEN ||
5084 		    (len != 2 * 16 && len != 2 * 32) ||
5085 		    hexstr2bin(pos, bss->mka_cak, len / 2)) {
5086 			wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
5087 				   line, pos);
5088 			return 1;
5089 		}
5090 		bss->mka_cak_len = len / 2;
5091 		bss->mka_psk_set |= MKA_PSK_SET_CAK;
5092 	} else if (os_strcmp(buf, "mka_ckn") == 0) {
5093 		size_t len = os_strlen(pos);
5094 
5095 		if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
5096 		    len < 2 || /* too short */
5097 		    len % 2 != 0 /* not an integral number of bytes */) {
5098 			wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
5099 				   line, pos);
5100 			return 1;
5101 		}
5102 		bss->mka_ckn_len = len / 2;
5103 		if (hexstr2bin(pos, bss->mka_ckn, bss->mka_ckn_len)) {
5104 			wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
5105 				   line, pos);
5106 			return -1;
5107 		}
5108 		bss->mka_psk_set |= MKA_PSK_SET_CKN;
5109 #endif /* CONFIG_MACSEC */
5110 	} else if (os_strcmp(buf, "disable_11n") == 0) {
5111 		bss->disable_11n = !!atoi(pos);
5112 	} else if (os_strcmp(buf, "disable_11ac") == 0) {
5113 		bss->disable_11ac = !!atoi(pos);
5114 	} else if (os_strcmp(buf, "disable_11ax") == 0) {
5115 		bss->disable_11ax = !!atoi(pos);
5116 	} else if (os_strcmp(buf, "disable_11be") == 0) {
5117 		bss->disable_11be = !!atoi(pos);
5118 #ifdef CONFIG_PASN
5119 #ifdef CONFIG_TESTING_OPTIONS
5120 	} else if (os_strcmp(buf, "force_kdk_derivation") == 0) {
5121 		bss->force_kdk_derivation = atoi(pos);
5122 	} else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) {
5123 		bss->pasn_corrupt_mic = atoi(pos);
5124 #endif /* CONFIG_TESTING_OPTIONS */
5125 	} else if (os_strcmp(buf, "pasn_groups") == 0) {
5126 		if (hostapd_parse_intlist(&bss->pasn_groups, pos)) {
5127 			wpa_printf(MSG_ERROR,
5128 				   "Line %d: Invalid pasn_groups value '%s'",
5129 				   line, pos);
5130 			return 1;
5131 		}
5132 	} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
5133 		bss->pasn_comeback_after = atoi(pos);
5134 	} else if (os_strcmp(buf, "pasn_noauth") == 0) {
5135 		bss->pasn_noauth = atoi(pos);
5136 #endif /* CONFIG_PASN */
5137 	} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
5138 		if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
5139 				   line, "ext_capa_mask", pos))
5140 			return 1;
5141 	} else if (os_strcmp(buf, "ext_capa") == 0) {
5142 		if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
5143 				   line, "ext_capa", pos))
5144 			return 1;
5145 	} else if (os_strcmp(buf, "rnr") == 0) {
5146 		bss->rnr = atoi(pos);
5147 	} else if (os_strcmp(buf, "ssid_protection") == 0) {
5148 		int val = atoi(pos);
5149 
5150 		if (val < 0 || val > 1)
5151 			return 1;
5152 		bss->ssid_protection = val;
5153 #ifdef CONFIG_IEEE80211BE
5154 	} else if (os_strcmp(buf, "ieee80211be") == 0) {
5155 		conf->ieee80211be = atoi(pos);
5156 	} else if (os_strcmp(buf, "eht_oper_chwidth") == 0) {
5157 		conf->eht_oper_chwidth = atoi(pos);
5158 	} else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) {
5159 		conf->eht_oper_centr_freq_seg0_idx = atoi(pos);
5160 	} else if (os_strcmp(buf, "eht_su_beamformer") == 0) {
5161 		conf->eht_phy_capab.su_beamformer = atoi(pos);
5162 	} else if (os_strcmp(buf, "eht_su_beamformee") == 0) {
5163 		conf->eht_phy_capab.su_beamformee = atoi(pos);
5164 	} else if (os_strcmp(buf, "eht_mu_beamformer") == 0) {
5165 		conf->eht_phy_capab.mu_beamformer = atoi(pos);
5166 	} else if (os_strcmp(buf, "eht_default_pe_duration") == 0) {
5167 		conf->eht_default_pe_duration = atoi(pos);
5168 	} else if (os_strcmp(buf, "punct_bitmap") == 0) {
5169 		if (get_u16(pos, line, &conf->punct_bitmap))
5170 			return 1;
5171 	} else if (os_strcmp(buf, "punct_acs_threshold") == 0) {
5172 		int val = atoi(pos);
5173 
5174 		if (val < 0 || val > 100) {
5175 			wpa_printf(MSG_ERROR,
5176 				   "Line %d: punct_acs_threshold must be between 0 and 100",
5177 				   line);
5178 			return 1;
5179 		}
5180 		conf->punct_acs_threshold = val;
5181 	} else if (os_strcmp(buf, "mld_ap") == 0) {
5182 		bss->mld_ap = !!atoi(pos);
5183 	} else if (os_strcmp(buf, "mld_addr") == 0) {
5184 		if (hwaddr_aton(pos, bss->mld_addr)) {
5185 			wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr",
5186 				   line);
5187 			return 1;
5188 		}
5189 	} else if (os_strcmp(buf, "eht_bw320_offset") == 0) {
5190 		conf->eht_bw320_offset = atoi(pos);
5191 #ifdef CONFIG_TESTING_OPTIONS
5192 	} else if (os_strcmp(buf, "eht_oper_puncturing_override") == 0) {
5193 		if (get_u16(pos, line, &bss->eht_oper_puncturing_override))
5194 			return 1;
5195 	} else if (os_strcmp(buf, "mld_indicate_disabled") == 0) {
5196 		bss->mld_indicate_disabled = atoi(pos);
5197 #endif /* CONFIG_TESTING_OPTIONS */
5198 #endif /* CONFIG_IEEE80211BE */
5199 	} else {
5200 		wpa_printf(MSG_ERROR,
5201 			   "Line %d: unknown configuration item '%s'",
5202 			   line, buf);
5203 		return 1;
5204 	}
5205 
5206 	return 0;
5207 }
5208 
5209 #ifdef CONFIG_OPEN_HARMONY_PATCH
hostapd_config_set_bandWidth(struct hostapd_config * conf,u8 freq_seg0_idx,u8 bandWidth)5210 static void hostapd_config_set_bandWidth(struct hostapd_config *conf,
5211 	u8 freq_seg0_idx, u8 bandWidth)
5212 {
5213 	conf->vht_oper_centr_freq_seg0_idx = freq_seg0_idx;
5214 	conf->vht_oper_chwidth = bandWidth;
5215 #ifdef CONFIG_IEEE80211AX
5216 	if (bandWidth == CHANWIDTH_160MHZ) {
5217 		/* only enable 11ax in ultra-fast cloning */
5218 		conf->ieee80211ax = 1;
5219 		conf->he_oper_centr_freq_seg0_idx = freq_seg0_idx;
5220 		conf->he_oper_chwidth = bandWidth;
5221 	}
5222 #endif
5223 }
5224 
CheckApBand(struct hostapd_config * conf)5225 static void CheckApBand(struct hostapd_config *conf)
5226 {
5227 	if (conf->ieee80211ac || conf->hw_mode != HOSTAPD_MODE_IEEE80211A) {
5228 		return;
5229 	}
5230 	if (((conf->channel > CHANNEL_161) || (conf->channel < CHANNEL_36)) ||
5231 		((conf->channel > CHANNEL_48) && (conf->channel < CHANNEL_149))) {
5232 		return;
5233 	}
5234 	wpa_printf(MSG_INFO, "try select 11ac");
5235 	switch(conf->channel) {
5236 		case CHANNEL_36:
5237 		case CHANNEL_44:
5238 			conf->secondary_channel = 1;
5239 			hostapd_config_set_bandWidth(conf, CHANNEL_42, CHANWIDTH_80MHZ);
5240 			if (conf->bandwidth == AP_BANDWIDTH_160M) {
5241 				hostapd_config_set_bandWidth(conf, CHANNEL_50, CHANWIDTH_160MHZ);
5242 				conf->vht_capab |= VHT_CAP_SHORT_GI_160;
5243 			}
5244 			break;
5245 		case CHANNEL_40:
5246 		case CHANNEL_48:
5247 			conf->secondary_channel = -1;
5248 			hostapd_config_set_bandWidth(conf, CHANNEL_42, CHANWIDTH_80MHZ);
5249 			if (conf->bandwidth == AP_BANDWIDTH_160M) {
5250 				hostapd_config_set_bandWidth(conf, CHANNEL_50, CHANWIDTH_160MHZ);
5251 				conf->vht_capab |= VHT_CAP_SHORT_GI_160;
5252 			}
5253 			break;
5254 		case CHANNEL_149:
5255 		case CHANNEL_157:
5256 			conf->secondary_channel = 1;
5257 			hostapd_config_set_bandWidth(conf, CHANNEL_155, CHANWIDTH_80MHZ);
5258 			break;
5259 		case CHANNEL_153:
5260 		case CHANNEL_161:
5261 			conf->secondary_channel = -1;
5262 			hostapd_config_set_bandWidth(conf, CHANNEL_155, CHANWIDTH_80MHZ);
5263 			break;
5264 		default:
5265 			break;
5266 	}
5267 	conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
5268 	conf->vht_capab |= VHT_CAP_SHORT_GI_80;
5269 	conf->ieee80211ac = 1;
5270 	wpa_printf(MSG_INFO, "11ac: %d, vht cap: %d, vht chwidth: %d, sec ch: %d",
5271 		conf->ieee80211ac, conf->vht_capab, conf->vht_oper_chwidth, conf->secondary_channel);
5272 }
5273 #endif
5274 
5275 #ifdef CONFIG_OPEN_HARMONY_PATCH
hostapd_passphrase_config_fill(struct hostapd_config * conf,const char * pass)5276 int hostapd_passphrase_config_fill(struct hostapd_config *conf, const char *pass)
5277 {
5278 	if (conf == NULL || pass == NULL || conf->last_bss == NULL) {
5279 		wpa_printf(MSG_ERROR, "conf or wpa_passphrase is null");
5280 		return 1;
5281 	}
5282 
5283 	struct hostapd_bss_config *bss;
5284 	bss = conf->last_bss;
5285 
5286     if (strcmp(pass, "") == 0) {
5287         wpa_printf(MSG_ERROR,"hostapd_passphrase_config_fill pass is null");
5288         return 0;
5289     }
5290 
5291 	os_free(bss->ssid.wpa_passphrase);
5292 	bss->ssid.wpa_passphrase = os_strdup(pass);
5293 	if (bss->ssid.wpa_passphrase) {
5294 		hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
5295 		bss->ssid.wpa_passphrase_set = 1;
5296 	}
5297 	return 0;
5298 }
5299 
set_global_hostapd_passphrase(const char * pass)5300 int set_global_hostapd_passphrase(const char *pass) {
5301     if (strlen(pass) > PASS_MAX_LENGTH) {
5302         return -1;
5303     }
5304     os_memset(g_hostapdPassphrase, 0, strlen(g_hostapdPassphrase));
5305     os_memcpy(g_hostapdPassphrase, pass, strlen(pass));
5306     return 0;
5307 }
5308 #endif
5309 
5310 /**
5311  * hostapd_config_read - Read and parse a configuration file
5312  * @fname: Configuration file name (including path, if needed)
5313  * Returns: Allocated configuration data structure
5314  */
hostapd_config_read(const char * fname)5315 struct hostapd_config * hostapd_config_read(const char *fname)
5316 {
5317 	struct hostapd_config *conf;
5318 	FILE *f;
5319 	char buf[4096], *pos;
5320 	int line = 0;
5321 	int errors = 0;
5322 	size_t i;
5323 
5324     f = fopen(fname, "r");
5325 	if (f == NULL) {
5326 		wpa_printf(MSG_ERROR, "Could not open configuration file '%s' for reading.", fname);
5327 		return NULL;
5328 	}
5329 
5330 	conf = hostapd_config_defaults();
5331 	if (conf == NULL) {
5332 		fclose(f);
5333 		return NULL;
5334 	}
5335 
5336 	/* set default driver based on configuration */
5337 	conf->driver = wpa_drivers[0];
5338 	if (conf->driver == NULL) {
5339 		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
5340 		hostapd_config_free(conf);
5341 		fclose(f);
5342 		return NULL;
5343 	}
5344 
5345 	conf->last_bss = conf->bss[0];
5346 
5347 	while (fgets(buf, sizeof(buf), f)) {
5348 		struct hostapd_bss_config *bss;
5349 
5350 		bss = conf->last_bss;
5351 		line++;
5352 
5353 		if (buf[0] == '#')
5354 			continue;
5355 		pos = buf;
5356 		while (*pos != '\0') {
5357 			if (*pos == '\n') {
5358 				*pos = '\0';
5359 				break;
5360 			}
5361 			pos++;
5362 		}
5363 		if (buf[0] == '\0')
5364 			continue;
5365 
5366 		pos = os_strchr(buf, '=');
5367 		if (pos == NULL) {
5368 			wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
5369 				   line, buf);
5370 			errors++;
5371 			continue;
5372 		}
5373 		*pos = '\0';
5374 		pos++;
5375 		errors += hostapd_config_fill(conf, bss, buf, pos, line);
5376 	}
5377 #ifdef CONFIG_OPEN_HARMONY_PATCH
5378 	errors += hostapd_passphrase_config_fill(conf, g_hostapdPassphrase);
5379 #endif
5380 
5381 	fclose(f);
5382 #ifdef CONFIG_OPEN_HARMONY_PATCH
5383     if ((conf->ieee80211n) && (HOSTAPD_MODE_IEEE80211G == conf->hw_mode)) {
5384         conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
5385         wpa_printf(MSG_INFO, "hostapd_config_read ht_capab HT_CAP_INFO_SHORT_GI20MHZ");
5386         if ((!(conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) && (!conf->ht20_set_flag)) {
5387             wpa_printf(MSG_INFO, "soft ap,11gn mode,try use HT40.");
5388             if (conf->channel < HT40_OFFSET_DOWN) {
5389                 /* HT40+ */
5390                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
5391                 conf->secondary_channel = 1;
5392                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
5393                 wpa_printf(MSG_INFO, "hostapd_config_read ht_capab HT_CAP_INFO_SHORT_GI40MHZ HT40+");
5394             } else if (conf->channel <= HT40_OFFSET_UP) {
5395                 /* HT40- */
5396                 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
5397                 conf->secondary_channel = -1;
5398                 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
5399                 wpa_printf(MSG_INFO, "hostapd_config_read ht_capab HT_CAP_INFO_SHORT_GI40MHZ HT40-");
5400             } else {
5401                 wpa_printf(MSG_INFO, "soft ap,channel 14,not change to HT40");
5402             }
5403         }
5404     }
5405 #ifdef CONFIG_IEEE80211AC
5406 	CheckApBand(conf);
5407 #endif
5408 #endif
5409 	for (i = 0; i < conf->num_bss; i++)
5410 		hostapd_set_security_params(conf->bss[i], 1);
5411 
5412 	if (hostapd_config_check(conf, 1))
5413 		errors++;
5414 
5415 #ifndef WPA_IGNORE_CONFIG_ERRORS
5416 	if (errors) {
5417         wpa_printf(MSG_ERROR, "%d errors found in configuration file '%s'", errors, fname);
5418         hostapd_config_free(conf);
5419 		conf = NULL;
5420 	}
5421 #endif /* WPA_IGNORE_CONFIG_ERRORS */
5422 
5423 	return conf;
5424 }
5425 
hostapd_set_iface(struct hostapd_config * conf,struct hostapd_bss_config * bss,const char * field,char * value)5426 int hostapd_set_iface(struct hostapd_config *conf,
5427 		      struct hostapd_bss_config *bss, const char *field,
5428 		      char *value)
5429 {
5430 	int errors;
5431 	size_t i;
5432 
5433 	errors = hostapd_config_fill(conf, bss, field, value, 0);
5434 	if (errors) {
5435 		wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
5436 			   "to value '%s'", field, value);
5437 		return -1;
5438 	}
5439 
5440 	for (i = 0; i < conf->num_bss; i++)
5441 		hostapd_set_security_params(conf->bss[i], 0);
5442 
5443 	if (hostapd_config_check(conf, 0)) {
5444 		wpa_printf(MSG_ERROR, "Configuration check failed");
5445 		return -1;
5446 	}
5447 
5448 	return 0;
5449 }
5450