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