Home | History | Annotate | Line # | Download | only in wpa_supplicant
config.c revision 1.1.1.4.4.1.2.1
      1 /*
      2  * WPA Supplicant / Configuration parser and common functions
      3  * Copyright (c) 2003-2015, 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 "includes.h"
     10 
     11 #include "common.h"
     12 #include "utils/uuid.h"
     13 #include "utils/ip_addr.h"
     14 #include "crypto/sha1.h"
     15 #include "rsn_supp/wpa.h"
     16 #include "eap_peer/eap.h"
     17 #include "p2p/p2p.h"
     18 #include "fst/fst.h"
     19 #include "config.h"
     20 
     21 
     22 #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
     23 #define NO_CONFIG_WRITE
     24 #endif
     25 
     26 /*
     27  * Structure for network configuration parsing. This data is used to implement
     28  * a generic parser for each network block variable. The table of configuration
     29  * variables is defined below in this file (ssid_fields[]).
     30  */
     31 struct parse_data {
     32 	/* Configuration variable name */
     33 	char *name;
     34 
     35 	/* Parser function for this variable. The parser functions return 0 or 1
     36 	 * to indicate success. Value 0 indicates that the parameter value may
     37 	 * have changed while value 1 means that the value did not change.
     38 	 * Error cases (failure to parse the string) are indicated by returning
     39 	 * -1. */
     40 	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
     41 		      int line, const char *value);
     42 
     43 #ifndef NO_CONFIG_WRITE
     44 	/* Writer function (i.e., to get the variable in text format from
     45 	 * internal presentation). */
     46 	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
     47 #endif /* NO_CONFIG_WRITE */
     48 
     49 	/* Variable specific parameters for the parser. */
     50 	void *param1, *param2, *param3, *param4;
     51 
     52 	/* 0 = this variable can be included in debug output and ctrl_iface
     53 	 * 1 = this variable contains key/private data and it must not be
     54 	 *     included in debug output unless explicitly requested. In
     55 	 *     addition, this variable will not be readable through the
     56 	 *     ctrl_iface.
     57 	 */
     58 	int key_data;
     59 };
     60 
     61 
     62 static int wpa_config_parse_str(const struct parse_data *data,
     63 				struct wpa_ssid *ssid,
     64 				int line, const char *value)
     65 {
     66 	size_t res_len, *dst_len, prev_len;
     67 	char **dst, *tmp;
     68 
     69 	if (os_strcmp(value, "NULL") == 0) {
     70 		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
     71 			   data->name);
     72 		tmp = NULL;
     73 		res_len = 0;
     74 		goto set;
     75 	}
     76 
     77 	tmp = wpa_config_parse_string(value, &res_len);
     78 	if (tmp == NULL) {
     79 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
     80 			   line, data->name,
     81 			   data->key_data ? "[KEY DATA REMOVED]" : value);
     82 		return -1;
     83 	}
     84 
     85 	if (data->key_data) {
     86 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
     87 				      (u8 *) tmp, res_len);
     88 	} else {
     89 		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
     90 				  (u8 *) tmp, res_len);
     91 	}
     92 
     93 	if (data->param3 && res_len < (size_t) data->param3) {
     94 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
     95 			   "min_len=%ld)", line, data->name,
     96 			   (unsigned long) res_len, (long) data->param3);
     97 		os_free(tmp);
     98 		return -1;
     99 	}
    100 
    101 	if (data->param4 && res_len > (size_t) data->param4) {
    102 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
    103 			   "max_len=%ld)", line, data->name,
    104 			   (unsigned long) res_len, (long) data->param4);
    105 		os_free(tmp);
    106 		return -1;
    107 	}
    108 
    109 set:
    110 	dst = (char **) (((u8 *) ssid) + (long) data->param1);
    111 	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
    112 
    113 	if (data->param2)
    114 		prev_len = *dst_len;
    115 	else if (*dst)
    116 		prev_len = os_strlen(*dst);
    117 	else
    118 		prev_len = 0;
    119 	if ((*dst == NULL && tmp == NULL) ||
    120 	    (*dst && tmp && prev_len == res_len &&
    121 	     os_memcmp(*dst, tmp, res_len) == 0)) {
    122 		/* No change to the previously configured value */
    123 		os_free(tmp);
    124 		return 1;
    125 	}
    126 
    127 	os_free(*dst);
    128 	*dst = tmp;
    129 	if (data->param2)
    130 		*dst_len = res_len;
    131 
    132 	return 0;
    133 }
    134 
    135 
    136 #ifndef NO_CONFIG_WRITE
    137 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
    138 {
    139 	char *buf;
    140 
    141 	buf = os_malloc(len + 3);
    142 	if (buf == NULL)
    143 		return NULL;
    144 	buf[0] = '"';
    145 	os_memcpy(buf + 1, value, len);
    146 	buf[len + 1] = '"';
    147 	buf[len + 2] = '\0';
    148 
    149 	return buf;
    150 }
    151 
    152 
    153 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
    154 {
    155 	char *buf;
    156 
    157 	buf = os_zalloc(2 * len + 1);
    158 	if (buf == NULL)
    159 		return NULL;
    160 	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
    161 
    162 	return buf;
    163 }
    164 
    165 
    166 static char * wpa_config_write_string(const u8 *value, size_t len)
    167 {
    168 	if (value == NULL)
    169 		return NULL;
    170 
    171 	if (is_hex(value, len))
    172 		return wpa_config_write_string_hex(value, len);
    173 	else
    174 		return wpa_config_write_string_ascii(value, len);
    175 }
    176 
    177 
    178 static char * wpa_config_write_str(const struct parse_data *data,
    179 				   struct wpa_ssid *ssid)
    180 {
    181 	size_t len;
    182 	char **src;
    183 
    184 	src = (char **) (((u8 *) ssid) + (long) data->param1);
    185 	if (*src == NULL)
    186 		return NULL;
    187 
    188 	if (data->param2)
    189 		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
    190 	else
    191 		len = os_strlen(*src);
    192 
    193 	return wpa_config_write_string((const u8 *) *src, len);
    194 }
    195 #endif /* NO_CONFIG_WRITE */
    196 
    197 
    198 static int wpa_config_parse_int(const struct parse_data *data,
    199 				struct wpa_ssid *ssid,
    200 				int line, const char *value)
    201 {
    202 	int val, *dst;
    203 	char *end;
    204 
    205 	dst = (int *) (((u8 *) ssid) + (long) data->param1);
    206 	val = strtol(value, &end, 0);
    207 	if (*end) {
    208 		wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
    209 			   line, value);
    210 		return -1;
    211 	}
    212 
    213 	if (*dst == val)
    214 		return 1;
    215 	*dst = val;
    216 	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
    217 
    218 	if (data->param3 && *dst < (long) data->param3) {
    219 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
    220 			   "min_value=%ld)", line, data->name, *dst,
    221 			   (long) data->param3);
    222 		*dst = (long) data->param3;
    223 		return -1;
    224 	}
    225 
    226 	if (data->param4 && *dst > (long) data->param4) {
    227 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
    228 			   "max_value=%ld)", line, data->name, *dst,
    229 			   (long) data->param4);
    230 		*dst = (long) data->param4;
    231 		return -1;
    232 	}
    233 
    234 	return 0;
    235 }
    236 
    237 
    238 #ifndef NO_CONFIG_WRITE
    239 static char * wpa_config_write_int(const struct parse_data *data,
    240 				   struct wpa_ssid *ssid)
    241 {
    242 	int *src, res;
    243 	char *value;
    244 
    245 	src = (int *) (((u8 *) ssid) + (long) data->param1);
    246 
    247 	value = os_malloc(20);
    248 	if (value == NULL)
    249 		return NULL;
    250 	res = os_snprintf(value, 20, "%d", *src);
    251 	if (os_snprintf_error(20, res)) {
    252 		os_free(value);
    253 		return NULL;
    254 	}
    255 	value[20 - 1] = '\0';
    256 	return value;
    257 }
    258 #endif /* NO_CONFIG_WRITE */
    259 
    260 
    261 static int wpa_config_parse_addr_list(const struct parse_data *data,
    262 				      int line, const char *value,
    263 				      u8 **list, size_t *num, char *name,
    264 				      u8 abort_on_error, u8 masked)
    265 {
    266 	const char *pos;
    267 	u8 *buf, *n, addr[2 * ETH_ALEN];
    268 	size_t count;
    269 
    270 	buf = NULL;
    271 	count = 0;
    272 
    273 	pos = value;
    274 	while (pos && *pos) {
    275 		while (*pos == ' ')
    276 			pos++;
    277 
    278 		if (hwaddr_masked_aton(pos, addr, &addr[ETH_ALEN], masked)) {
    279 			if (abort_on_error || count == 0) {
    280 				wpa_printf(MSG_ERROR,
    281 					   "Line %d: Invalid %s address '%s'",
    282 					   line, name, value);
    283 				os_free(buf);
    284 				return -1;
    285 			}
    286 			/* continue anyway since this could have been from a
    287 			 * truncated configuration file line */
    288 			wpa_printf(MSG_INFO,
    289 				   "Line %d: Ignore likely truncated %s address '%s'",
    290 				   line, name, pos);
    291 		} else {
    292 			n = os_realloc_array(buf, count + 1, 2 * ETH_ALEN);
    293 			if (n == NULL) {
    294 				os_free(buf);
    295 				return -1;
    296 			}
    297 			buf = n;
    298 			os_memmove(buf + 2 * ETH_ALEN, buf,
    299 				   count * 2 * ETH_ALEN);
    300 			os_memcpy(buf, addr, 2 * ETH_ALEN);
    301 			count++;
    302 			wpa_printf(MSG_MSGDUMP,
    303 				   "%s: addr=" MACSTR " mask=" MACSTR,
    304 				   name, MAC2STR(addr),
    305 				   MAC2STR(&addr[ETH_ALEN]));
    306 		}
    307 
    308 		pos = os_strchr(pos, ' ');
    309 	}
    310 
    311 	os_free(*list);
    312 	*list = buf;
    313 	*num = count;
    314 
    315 	return 0;
    316 }
    317 
    318 
    319 #ifndef NO_CONFIG_WRITE
    320 static char * wpa_config_write_addr_list(const struct parse_data *data,
    321 					 const u8 *list, size_t num, char *name)
    322 {
    323 	char *value, *end, *pos;
    324 	int res;
    325 	size_t i;
    326 
    327 	if (list == NULL || num == 0)
    328 		return NULL;
    329 
    330 	value = os_malloc(2 * 20 * num);
    331 	if (value == NULL)
    332 		return NULL;
    333 	pos = value;
    334 	end = value + 2 * 20 * num;
    335 
    336 	for (i = num; i > 0; i--) {
    337 		const u8 *a = list + (i - 1) * 2 * ETH_ALEN;
    338 		const u8 *m = a + ETH_ALEN;
    339 
    340 		if (i < num)
    341 			*pos++ = ' ';
    342 		res = hwaddr_mask_txt(pos, end - pos, a, m);
    343 		if (res < 0) {
    344 			os_free(value);
    345 			return NULL;
    346 		}
    347 		pos += res;
    348 	}
    349 
    350 	return value;
    351 }
    352 #endif /* NO_CONFIG_WRITE */
    353 
    354 static int wpa_config_parse_bssid(const struct parse_data *data,
    355 				  struct wpa_ssid *ssid, int line,
    356 				  const char *value)
    357 {
    358 	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
    359 	    os_strcmp(value, "any") == 0) {
    360 		ssid->bssid_set = 0;
    361 		wpa_printf(MSG_MSGDUMP, "BSSID any");
    362 		return 0;
    363 	}
    364 	if (hwaddr_aton(value, ssid->bssid)) {
    365 		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
    366 			   line, value);
    367 		return -1;
    368 	}
    369 	ssid->bssid_set = 1;
    370 	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
    371 	return 0;
    372 }
    373 
    374 
    375 #ifndef NO_CONFIG_WRITE
    376 static char * wpa_config_write_bssid(const struct parse_data *data,
    377 				     struct wpa_ssid *ssid)
    378 {
    379 	char *value;
    380 	int res;
    381 
    382 	if (!ssid->bssid_set)
    383 		return NULL;
    384 
    385 	value = os_malloc(20);
    386 	if (value == NULL)
    387 		return NULL;
    388 	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
    389 	if (os_snprintf_error(20, res)) {
    390 		os_free(value);
    391 		return NULL;
    392 	}
    393 	value[20 - 1] = '\0';
    394 	return value;
    395 }
    396 #endif /* NO_CONFIG_WRITE */
    397 
    398 
    399 static int wpa_config_parse_bssid_blacklist(const struct parse_data *data,
    400 					    struct wpa_ssid *ssid, int line,
    401 					    const char *value)
    402 {
    403 	return wpa_config_parse_addr_list(data, line, value,
    404 					  &ssid->bssid_blacklist,
    405 					  &ssid->num_bssid_blacklist,
    406 					  "bssid_blacklist", 1, 1);
    407 }
    408 
    409 
    410 #ifndef NO_CONFIG_WRITE
    411 static char * wpa_config_write_bssid_blacklist(const struct parse_data *data,
    412 					       struct wpa_ssid *ssid)
    413 {
    414 	return wpa_config_write_addr_list(data, ssid->bssid_blacklist,
    415 					  ssid->num_bssid_blacklist,
    416 					  "bssid_blacklist");
    417 }
    418 #endif /* NO_CONFIG_WRITE */
    419 
    420 
    421 static int wpa_config_parse_bssid_whitelist(const struct parse_data *data,
    422 					    struct wpa_ssid *ssid, int line,
    423 					    const char *value)
    424 {
    425 	return wpa_config_parse_addr_list(data, line, value,
    426 					  &ssid->bssid_whitelist,
    427 					  &ssid->num_bssid_whitelist,
    428 					  "bssid_whitelist", 1, 1);
    429 }
    430 
    431 
    432 #ifndef NO_CONFIG_WRITE
    433 static char * wpa_config_write_bssid_whitelist(const struct parse_data *data,
    434 					       struct wpa_ssid *ssid)
    435 {
    436 	return wpa_config_write_addr_list(data, ssid->bssid_whitelist,
    437 					  ssid->num_bssid_whitelist,
    438 					  "bssid_whitelist");
    439 }
    440 #endif /* NO_CONFIG_WRITE */
    441 
    442 
    443 static int wpa_config_parse_psk(const struct parse_data *data,
    444 				struct wpa_ssid *ssid, int line,
    445 				const char *value)
    446 {
    447 #ifdef CONFIG_EXT_PASSWORD
    448 	if (os_strncmp(value, "ext:", 4) == 0) {
    449 		str_clear_free(ssid->passphrase);
    450 		ssid->passphrase = NULL;
    451 		ssid->psk_set = 0;
    452 		os_free(ssid->ext_psk);
    453 		ssid->ext_psk = os_strdup(value + 4);
    454 		if (ssid->ext_psk == NULL)
    455 			return -1;
    456 		wpa_printf(MSG_DEBUG, "PSK: External password '%s'",
    457 			   ssid->ext_psk);
    458 		return 0;
    459 	}
    460 #endif /* CONFIG_EXT_PASSWORD */
    461 
    462 	if (*value == '"') {
    463 #ifndef CONFIG_NO_PBKDF2
    464 		const char *pos;
    465 		size_t len;
    466 
    467 		value++;
    468 		pos = os_strrchr(value, '"');
    469 		if (pos)
    470 			len = pos - value;
    471 		else
    472 			len = os_strlen(value);
    473 		if (len < 8 || len > 63) {
    474 			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
    475 				   "length %lu (expected: 8..63) '%s'.",
    476 				   line, (unsigned long) len, value);
    477 			return -1;
    478 		}
    479 		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
    480 				      (u8 *) value, len);
    481 		if (has_ctrl_char((u8 *) value, len)) {
    482 			wpa_printf(MSG_ERROR,
    483 				   "Line %d: Invalid passphrase character",
    484 				   line);
    485 			return -1;
    486 		}
    487 		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
    488 		    os_memcmp(ssid->passphrase, value, len) == 0) {
    489 			/* No change to the previously configured value */
    490 			return 1;
    491 		}
    492 		ssid->psk_set = 0;
    493 		str_clear_free(ssid->passphrase);
    494 		ssid->passphrase = dup_binstr(value, len);
    495 		if (ssid->passphrase == NULL)
    496 			return -1;
    497 		return 0;
    498 #else /* CONFIG_NO_PBKDF2 */
    499 		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
    500 			   "supported.", line);
    501 		return -1;
    502 #endif /* CONFIG_NO_PBKDF2 */
    503 	}
    504 
    505 	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
    506 	    value[PMK_LEN * 2] != '\0') {
    507 		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
    508 			   line, value);
    509 		return -1;
    510 	}
    511 
    512 	str_clear_free(ssid->passphrase);
    513 	ssid->passphrase = NULL;
    514 
    515 	ssid->psk_set = 1;
    516 	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
    517 	return 0;
    518 }
    519 
    520 
    521 #ifndef NO_CONFIG_WRITE
    522 static char * wpa_config_write_psk(const struct parse_data *data,
    523 				   struct wpa_ssid *ssid)
    524 {
    525 #ifdef CONFIG_EXT_PASSWORD
    526 	if (ssid->ext_psk) {
    527 		size_t len = 4 + os_strlen(ssid->ext_psk) + 1;
    528 		char *buf = os_malloc(len);
    529 		int res;
    530 
    531 		if (buf == NULL)
    532 			return NULL;
    533 		res = os_snprintf(buf, len, "ext:%s", ssid->ext_psk);
    534 		if (os_snprintf_error(len, res)) {
    535 			os_free(buf);
    536 			buf = NULL;
    537 		}
    538 		return buf;
    539 	}
    540 #endif /* CONFIG_EXT_PASSWORD */
    541 
    542 	if (ssid->passphrase)
    543 		return wpa_config_write_string_ascii(
    544 			(const u8 *) ssid->passphrase,
    545 			os_strlen(ssid->passphrase));
    546 
    547 	if (ssid->psk_set)
    548 		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
    549 
    550 	return NULL;
    551 }
    552 #endif /* NO_CONFIG_WRITE */
    553 
    554 
    555 static int wpa_config_parse_proto(const struct parse_data *data,
    556 				  struct wpa_ssid *ssid, int line,
    557 				  const char *value)
    558 {
    559 	int val = 0, last, errors = 0;
    560 	char *start, *end, *buf;
    561 
    562 	buf = os_strdup(value);
    563 	if (buf == NULL)
    564 		return -1;
    565 	start = buf;
    566 
    567 	while (*start != '\0') {
    568 		while (*start == ' ' || *start == '\t')
    569 			start++;
    570 		if (*start == '\0')
    571 			break;
    572 		end = start;
    573 		while (*end != ' ' && *end != '\t' && *end != '\0')
    574 			end++;
    575 		last = *end == '\0';
    576 		*end = '\0';
    577 		if (os_strcmp(start, "WPA") == 0)
    578 			val |= WPA_PROTO_WPA;
    579 		else if (os_strcmp(start, "RSN") == 0 ||
    580 			 os_strcmp(start, "WPA2") == 0)
    581 			val |= WPA_PROTO_RSN;
    582 		else if (os_strcmp(start, "OSEN") == 0)
    583 			val |= WPA_PROTO_OSEN;
    584 		else {
    585 			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
    586 				   line, start);
    587 			errors++;
    588 		}
    589 
    590 		if (last)
    591 			break;
    592 		start = end + 1;
    593 	}
    594 	os_free(buf);
    595 
    596 	if (val == 0) {
    597 		wpa_printf(MSG_ERROR,
    598 			   "Line %d: no proto values configured.", line);
    599 		errors++;
    600 	}
    601 
    602 	if (!errors && ssid->proto == val)
    603 		return 1;
    604 	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
    605 	ssid->proto = val;
    606 	return errors ? -1 : 0;
    607 }
    608 
    609 
    610 #ifndef NO_CONFIG_WRITE
    611 static char * wpa_config_write_proto(const struct parse_data *data,
    612 				     struct wpa_ssid *ssid)
    613 {
    614 	int ret;
    615 	char *buf, *pos, *end;
    616 
    617 	pos = buf = os_zalloc(20);
    618 	if (buf == NULL)
    619 		return NULL;
    620 	end = buf + 20;
    621 
    622 	if (ssid->proto & WPA_PROTO_WPA) {
    623 		ret = os_snprintf(pos, end - pos, "%sWPA",
    624 				  pos == buf ? "" : " ");
    625 		if (os_snprintf_error(end - pos, ret))
    626 			return buf;
    627 		pos += ret;
    628 	}
    629 
    630 	if (ssid->proto & WPA_PROTO_RSN) {
    631 		ret = os_snprintf(pos, end - pos, "%sRSN",
    632 				  pos == buf ? "" : " ");
    633 		if (os_snprintf_error(end - pos, ret))
    634 			return buf;
    635 		pos += ret;
    636 	}
    637 
    638 	if (ssid->proto & WPA_PROTO_OSEN) {
    639 		ret = os_snprintf(pos, end - pos, "%sOSEN",
    640 				  pos == buf ? "" : " ");
    641 		if (os_snprintf_error(end - pos, ret))
    642 			return buf;
    643 		pos += ret;
    644 	}
    645 
    646 	if (pos == buf) {
    647 		os_free(buf);
    648 		buf = NULL;
    649 	}
    650 
    651 	return buf;
    652 }
    653 #endif /* NO_CONFIG_WRITE */
    654 
    655 
    656 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
    657 				     struct wpa_ssid *ssid, int line,
    658 				     const char *value)
    659 {
    660 	int val = 0, last, errors = 0;
    661 	char *start, *end, *buf;
    662 
    663 	buf = os_strdup(value);
    664 	if (buf == NULL)
    665 		return -1;
    666 	start = buf;
    667 
    668 	while (*start != '\0') {
    669 		while (*start == ' ' || *start == '\t')
    670 			start++;
    671 		if (*start == '\0')
    672 			break;
    673 		end = start;
    674 		while (*end != ' ' && *end != '\t' && *end != '\0')
    675 			end++;
    676 		last = *end == '\0';
    677 		*end = '\0';
    678 		if (os_strcmp(start, "WPA-PSK") == 0)
    679 			val |= WPA_KEY_MGMT_PSK;
    680 		else if (os_strcmp(start, "WPA-EAP") == 0)
    681 			val |= WPA_KEY_MGMT_IEEE8021X;
    682 		else if (os_strcmp(start, "IEEE8021X") == 0)
    683 			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
    684 		else if (os_strcmp(start, "NONE") == 0)
    685 			val |= WPA_KEY_MGMT_NONE;
    686 		else if (os_strcmp(start, "WPA-NONE") == 0)
    687 			val |= WPA_KEY_MGMT_WPA_NONE;
    688 #ifdef CONFIG_IEEE80211R
    689 		else if (os_strcmp(start, "FT-PSK") == 0)
    690 			val |= WPA_KEY_MGMT_FT_PSK;
    691 		else if (os_strcmp(start, "FT-EAP") == 0)
    692 			val |= WPA_KEY_MGMT_FT_IEEE8021X;
    693 #endif /* CONFIG_IEEE80211R */
    694 #ifdef CONFIG_IEEE80211W
    695 		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
    696 			val |= WPA_KEY_MGMT_PSK_SHA256;
    697 		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
    698 			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
    699 #endif /* CONFIG_IEEE80211W */
    700 #ifdef CONFIG_WPS
    701 		else if (os_strcmp(start, "WPS") == 0)
    702 			val |= WPA_KEY_MGMT_WPS;
    703 #endif /* CONFIG_WPS */
    704 #ifdef CONFIG_SAE
    705 		else if (os_strcmp(start, "SAE") == 0)
    706 			val |= WPA_KEY_MGMT_SAE;
    707 		else if (os_strcmp(start, "FT-SAE") == 0)
    708 			val |= WPA_KEY_MGMT_FT_SAE;
    709 #endif /* CONFIG_SAE */
    710 #ifdef CONFIG_HS20
    711 		else if (os_strcmp(start, "OSEN") == 0)
    712 			val |= WPA_KEY_MGMT_OSEN;
    713 #endif /* CONFIG_HS20 */
    714 #ifdef CONFIG_SUITEB
    715 		else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
    716 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
    717 #endif /* CONFIG_SUITEB */
    718 #ifdef CONFIG_SUITEB192
    719 		else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
    720 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
    721 #endif /* CONFIG_SUITEB192 */
    722 		else {
    723 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
    724 				   line, start);
    725 			errors++;
    726 		}
    727 
    728 		if (last)
    729 			break;
    730 		start = end + 1;
    731 	}
    732 	os_free(buf);
    733 
    734 	if (val == 0) {
    735 		wpa_printf(MSG_ERROR,
    736 			   "Line %d: no key_mgmt values configured.", line);
    737 		errors++;
    738 	}
    739 
    740 	if (!errors && ssid->key_mgmt == val)
    741 		return 1;
    742 	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
    743 	ssid->key_mgmt = val;
    744 	return errors ? -1 : 0;
    745 }
    746 
    747 
    748 #ifndef NO_CONFIG_WRITE
    749 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
    750 					struct wpa_ssid *ssid)
    751 {
    752 	char *buf, *pos, *end;
    753 	int ret;
    754 
    755 	pos = buf = os_zalloc(100);
    756 	if (buf == NULL)
    757 		return NULL;
    758 	end = buf + 100;
    759 
    760 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
    761 		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
    762 				  pos == buf ? "" : " ");
    763 		if (os_snprintf_error(end - pos, ret)) {
    764 			end[-1] = '\0';
    765 			return buf;
    766 		}
    767 		pos += ret;
    768 	}
    769 
    770 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    771 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
    772 				  pos == buf ? "" : " ");
    773 		if (os_snprintf_error(end - pos, ret)) {
    774 			end[-1] = '\0';
    775 			return buf;
    776 		}
    777 		pos += ret;
    778 	}
    779 
    780 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    781 		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
    782 				  pos == buf ? "" : " ");
    783 		if (os_snprintf_error(end - pos, ret)) {
    784 			end[-1] = '\0';
    785 			return buf;
    786 		}
    787 		pos += ret;
    788 	}
    789 
    790 	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
    791 		ret = os_snprintf(pos, end - pos, "%sNONE",
    792 				  pos == buf ? "" : " ");
    793 		if (os_snprintf_error(end - pos, ret)) {
    794 			end[-1] = '\0';
    795 			return buf;
    796 		}
    797 		pos += ret;
    798 	}
    799 
    800 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    801 		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
    802 				  pos == buf ? "" : " ");
    803 		if (os_snprintf_error(end - pos, ret)) {
    804 			end[-1] = '\0';
    805 			return buf;
    806 		}
    807 		pos += ret;
    808 	}
    809 
    810 #ifdef CONFIG_IEEE80211R
    811 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    812 		ret = os_snprintf(pos, end - pos, "%sFT-PSK",
    813 				  pos == buf ? "" : " ");
    814 		if (os_snprintf_error(end - pos, ret)) {
    815 			end[-1] = '\0';
    816 			return buf;
    817 		}
    818 		pos += ret;
    819 	}
    820 
    821 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    822 		ret = os_snprintf(pos, end - pos, "%sFT-EAP",
    823 				  pos == buf ? "" : " ");
    824 		if (os_snprintf_error(end - pos, ret)) {
    825 			end[-1] = '\0';
    826 			return buf;
    827 		}
    828 		pos += ret;
    829 	}
    830 #endif /* CONFIG_IEEE80211R */
    831 
    832 #ifdef CONFIG_IEEE80211W
    833 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    834 		ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
    835 				  pos == buf ? "" : " ");
    836 		if (os_snprintf_error(end - pos, ret)) {
    837 			end[-1] = '\0';
    838 			return buf;
    839 		}
    840 		pos += ret;
    841 	}
    842 
    843 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    844 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
    845 				  pos == buf ? "" : " ");
    846 		if (os_snprintf_error(end - pos, ret)) {
    847 			end[-1] = '\0';
    848 			return buf;
    849 		}
    850 		pos += ret;
    851 	}
    852 #endif /* CONFIG_IEEE80211W */
    853 
    854 #ifdef CONFIG_WPS
    855 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
    856 		ret = os_snprintf(pos, end - pos, "%sWPS",
    857 				  pos == buf ? "" : " ");
    858 		if (os_snprintf_error(end - pos, ret)) {
    859 			end[-1] = '\0';
    860 			return buf;
    861 		}
    862 		pos += ret;
    863 	}
    864 #endif /* CONFIG_WPS */
    865 
    866 #ifdef CONFIG_SAE
    867 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
    868 		ret = os_snprintf(pos, end - pos, "%sSAE",
    869 				  pos == buf ? "" : " ");
    870 		if (os_snprintf_error(end - pos, ret)) {
    871 			end[-1] = '\0';
    872 			return buf;
    873 		}
    874 		pos += ret;
    875 	}
    876 
    877 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_SAE) {
    878 		ret = os_snprintf(pos, end - pos, "%sFT-SAE",
    879 				  pos == buf ? "" : " ");
    880 		if (os_snprintf_error(end - pos, ret)) {
    881 			end[-1] = '\0';
    882 			return buf;
    883 		}
    884 		pos += ret;
    885 	}
    886 #endif /* CONFIG_SAE */
    887 
    888 #ifdef CONFIG_HS20
    889 	if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN) {
    890 		ret = os_snprintf(pos, end - pos, "%sOSEN",
    891 				  pos == buf ? "" : " ");
    892 		if (os_snprintf_error(end - pos, ret)) {
    893 			end[-1] = '\0';
    894 			return buf;
    895 		}
    896 		pos += ret;
    897 	}
    898 #endif /* CONFIG_HS20 */
    899 
    900 #ifdef CONFIG_SUITEB
    901 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
    902 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B",
    903 				  pos == buf ? "" : " ");
    904 		if (os_snprintf_error(end - pos, ret)) {
    905 			end[-1] = '\0';
    906 			return buf;
    907 		}
    908 		pos += ret;
    909 	}
    910 #endif /* CONFIG_SUITEB */
    911 
    912 #ifdef CONFIG_SUITEB192
    913 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
    914 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B-192",
    915 				  pos == buf ? "" : " ");
    916 		if (os_snprintf_error(end - pos, ret)) {
    917 			end[-1] = '\0';
    918 			return buf;
    919 		}
    920 		pos += ret;
    921 	}
    922 #endif /* CONFIG_SUITEB192 */
    923 
    924 	if (pos == buf) {
    925 		os_free(buf);
    926 		buf = NULL;
    927 	}
    928 
    929 	return buf;
    930 }
    931 #endif /* NO_CONFIG_WRITE */
    932 
    933 
    934 static int wpa_config_parse_cipher(int line, const char *value)
    935 {
    936 #ifdef CONFIG_NO_WPA
    937 	return -1;
    938 #else /* CONFIG_NO_WPA */
    939 	int val = wpa_parse_cipher(value);
    940 	if (val < 0) {
    941 		wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
    942 			   line, value);
    943 		return -1;
    944 	}
    945 	if (val == 0) {
    946 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
    947 			   line);
    948 		return -1;
    949 	}
    950 	return val;
    951 #endif /* CONFIG_NO_WPA */
    952 }
    953 
    954 
    955 #ifndef NO_CONFIG_WRITE
    956 static char * wpa_config_write_cipher(int cipher)
    957 {
    958 #ifdef CONFIG_NO_WPA
    959 	return NULL;
    960 #else /* CONFIG_NO_WPA */
    961 	char *buf = os_zalloc(50);
    962 	if (buf == NULL)
    963 		return NULL;
    964 
    965 	if (wpa_write_ciphers(buf, buf + 50, cipher, " ") < 0) {
    966 		os_free(buf);
    967 		return NULL;
    968 	}
    969 
    970 	return buf;
    971 #endif /* CONFIG_NO_WPA */
    972 }
    973 #endif /* NO_CONFIG_WRITE */
    974 
    975 
    976 static int wpa_config_parse_pairwise(const struct parse_data *data,
    977 				     struct wpa_ssid *ssid, int line,
    978 				     const char *value)
    979 {
    980 	int val;
    981 	val = wpa_config_parse_cipher(line, value);
    982 	if (val == -1)
    983 		return -1;
    984 	if (val & ~WPA_ALLOWED_PAIRWISE_CIPHERS) {
    985 		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
    986 			   "(0x%x).", line, val);
    987 		return -1;
    988 	}
    989 
    990 	if (ssid->pairwise_cipher == val)
    991 		return 1;
    992 	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
    993 	ssid->pairwise_cipher = val;
    994 	return 0;
    995 }
    996 
    997 
    998 #ifndef NO_CONFIG_WRITE
    999 static char * wpa_config_write_pairwise(const struct parse_data *data,
   1000 					struct wpa_ssid *ssid)
   1001 {
   1002 	return wpa_config_write_cipher(ssid->pairwise_cipher);
   1003 }
   1004 #endif /* NO_CONFIG_WRITE */
   1005 
   1006 
   1007 static int wpa_config_parse_group(const struct parse_data *data,
   1008 				  struct wpa_ssid *ssid, int line,
   1009 				  const char *value)
   1010 {
   1011 	int val;
   1012 	val = wpa_config_parse_cipher(line, value);
   1013 	if (val == -1)
   1014 		return -1;
   1015 
   1016 	/*
   1017 	 * Backwards compatibility - filter out WEP ciphers that were previously
   1018 	 * allowed.
   1019 	 */
   1020 	val &= ~(WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40);
   1021 
   1022 	if (val & ~WPA_ALLOWED_GROUP_CIPHERS) {
   1023 		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
   1024 			   "(0x%x).", line, val);
   1025 		return -1;
   1026 	}
   1027 
   1028 	if (ssid->group_cipher == val)
   1029 		return 1;
   1030 	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
   1031 	ssid->group_cipher = val;
   1032 	return 0;
   1033 }
   1034 
   1035 
   1036 #ifndef NO_CONFIG_WRITE
   1037 static char * wpa_config_write_group(const struct parse_data *data,
   1038 				     struct wpa_ssid *ssid)
   1039 {
   1040 	return wpa_config_write_cipher(ssid->group_cipher);
   1041 }
   1042 #endif /* NO_CONFIG_WRITE */
   1043 
   1044 
   1045 static int wpa_config_parse_auth_alg(const struct parse_data *data,
   1046 				     struct wpa_ssid *ssid, int line,
   1047 				     const char *value)
   1048 {
   1049 	int val = 0, last, errors = 0;
   1050 	char *start, *end, *buf;
   1051 
   1052 	buf = os_strdup(value);
   1053 	if (buf == NULL)
   1054 		return -1;
   1055 	start = buf;
   1056 
   1057 	while (*start != '\0') {
   1058 		while (*start == ' ' || *start == '\t')
   1059 			start++;
   1060 		if (*start == '\0')
   1061 			break;
   1062 		end = start;
   1063 		while (*end != ' ' && *end != '\t' && *end != '\0')
   1064 			end++;
   1065 		last = *end == '\0';
   1066 		*end = '\0';
   1067 		if (os_strcmp(start, "OPEN") == 0)
   1068 			val |= WPA_AUTH_ALG_OPEN;
   1069 		else if (os_strcmp(start, "SHARED") == 0)
   1070 			val |= WPA_AUTH_ALG_SHARED;
   1071 		else if (os_strcmp(start, "LEAP") == 0)
   1072 			val |= WPA_AUTH_ALG_LEAP;
   1073 		else {
   1074 			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
   1075 				   line, start);
   1076 			errors++;
   1077 		}
   1078 
   1079 		if (last)
   1080 			break;
   1081 		start = end + 1;
   1082 	}
   1083 	os_free(buf);
   1084 
   1085 	if (val == 0) {
   1086 		wpa_printf(MSG_ERROR,
   1087 			   "Line %d: no auth_alg values configured.", line);
   1088 		errors++;
   1089 	}
   1090 
   1091 	if (!errors && ssid->auth_alg == val)
   1092 		return 1;
   1093 	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
   1094 	ssid->auth_alg = val;
   1095 	return errors ? -1 : 0;
   1096 }
   1097 
   1098 
   1099 #ifndef NO_CONFIG_WRITE
   1100 static char * wpa_config_write_auth_alg(const struct parse_data *data,
   1101 					struct wpa_ssid *ssid)
   1102 {
   1103 	char *buf, *pos, *end;
   1104 	int ret;
   1105 
   1106 	pos = buf = os_zalloc(30);
   1107 	if (buf == NULL)
   1108 		return NULL;
   1109 	end = buf + 30;
   1110 
   1111 	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
   1112 		ret = os_snprintf(pos, end - pos, "%sOPEN",
   1113 				  pos == buf ? "" : " ");
   1114 		if (os_snprintf_error(end - pos, ret)) {
   1115 			end[-1] = '\0';
   1116 			return buf;
   1117 		}
   1118 		pos += ret;
   1119 	}
   1120 
   1121 	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
   1122 		ret = os_snprintf(pos, end - pos, "%sSHARED",
   1123 				  pos == buf ? "" : " ");
   1124 		if (os_snprintf_error(end - pos, ret)) {
   1125 			end[-1] = '\0';
   1126 			return buf;
   1127 		}
   1128 		pos += ret;
   1129 	}
   1130 
   1131 	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
   1132 		ret = os_snprintf(pos, end - pos, "%sLEAP",
   1133 				  pos == buf ? "" : " ");
   1134 		if (os_snprintf_error(end - pos, ret)) {
   1135 			end[-1] = '\0';
   1136 			return buf;
   1137 		}
   1138 		pos += ret;
   1139 	}
   1140 
   1141 	if (pos == buf) {
   1142 		os_free(buf);
   1143 		buf = NULL;
   1144 	}
   1145 
   1146 	return buf;
   1147 }
   1148 #endif /* NO_CONFIG_WRITE */
   1149 
   1150 
   1151 static int * wpa_config_parse_int_array(const char *value)
   1152 {
   1153 	int *freqs;
   1154 	size_t used, len;
   1155 	const char *pos;
   1156 
   1157 	used = 0;
   1158 	len = 10;
   1159 	freqs = os_calloc(len + 1, sizeof(int));
   1160 	if (freqs == NULL)
   1161 		return NULL;
   1162 
   1163 	pos = value;
   1164 	while (pos) {
   1165 		while (*pos == ' ')
   1166 			pos++;
   1167 		if (used == len) {
   1168 			int *n;
   1169 			size_t i;
   1170 			n = os_realloc_array(freqs, len * 2 + 1, sizeof(int));
   1171 			if (n == NULL) {
   1172 				os_free(freqs);
   1173 				return NULL;
   1174 			}
   1175 			for (i = len; i <= len * 2; i++)
   1176 				n[i] = 0;
   1177 			freqs = n;
   1178 			len *= 2;
   1179 		}
   1180 
   1181 		freqs[used] = atoi(pos);
   1182 		if (freqs[used] == 0)
   1183 			break;
   1184 		used++;
   1185 		pos = os_strchr(pos + 1, ' ');
   1186 	}
   1187 
   1188 	return freqs;
   1189 }
   1190 
   1191 
   1192 static int wpa_config_parse_scan_freq(const struct parse_data *data,
   1193 				      struct wpa_ssid *ssid, int line,
   1194 				      const char *value)
   1195 {
   1196 	int *freqs;
   1197 
   1198 	freqs = wpa_config_parse_int_array(value);
   1199 	if (freqs == NULL)
   1200 		return -1;
   1201 	if (freqs[0] == 0) {
   1202 		os_free(freqs);
   1203 		freqs = NULL;
   1204 	}
   1205 	os_free(ssid->scan_freq);
   1206 	ssid->scan_freq = freqs;
   1207 
   1208 	return 0;
   1209 }
   1210 
   1211 
   1212 static int wpa_config_parse_freq_list(const struct parse_data *data,
   1213 				      struct wpa_ssid *ssid, int line,
   1214 				      const char *value)
   1215 {
   1216 	int *freqs;
   1217 
   1218 	freqs = wpa_config_parse_int_array(value);
   1219 	if (freqs == NULL)
   1220 		return -1;
   1221 	if (freqs[0] == 0) {
   1222 		os_free(freqs);
   1223 		freqs = NULL;
   1224 	}
   1225 	os_free(ssid->freq_list);
   1226 	ssid->freq_list = freqs;
   1227 
   1228 	return 0;
   1229 }
   1230 
   1231 
   1232 #ifndef NO_CONFIG_WRITE
   1233 static char * wpa_config_write_freqs(const struct parse_data *data,
   1234 				     const int *freqs)
   1235 {
   1236 	char *buf, *pos, *end;
   1237 	int i, ret;
   1238 	size_t count;
   1239 
   1240 	if (freqs == NULL)
   1241 		return NULL;
   1242 
   1243 	count = 0;
   1244 	for (i = 0; freqs[i]; i++)
   1245 		count++;
   1246 
   1247 	pos = buf = os_zalloc(10 * count + 1);
   1248 	if (buf == NULL)
   1249 		return NULL;
   1250 	end = buf + 10 * count + 1;
   1251 
   1252 	for (i = 0; freqs[i]; i++) {
   1253 		ret = os_snprintf(pos, end - pos, "%s%u",
   1254 				  i == 0 ? "" : " ", freqs[i]);
   1255 		if (os_snprintf_error(end - pos, ret)) {
   1256 			end[-1] = '\0';
   1257 			return buf;
   1258 		}
   1259 		pos += ret;
   1260 	}
   1261 
   1262 	return buf;
   1263 }
   1264 
   1265 
   1266 static char * wpa_config_write_scan_freq(const struct parse_data *data,
   1267 					 struct wpa_ssid *ssid)
   1268 {
   1269 	return wpa_config_write_freqs(data, ssid->scan_freq);
   1270 }
   1271 
   1272 
   1273 static char * wpa_config_write_freq_list(const struct parse_data *data,
   1274 					 struct wpa_ssid *ssid)
   1275 {
   1276 	return wpa_config_write_freqs(data, ssid->freq_list);
   1277 }
   1278 #endif /* NO_CONFIG_WRITE */
   1279 
   1280 
   1281 #ifdef IEEE8021X_EAPOL
   1282 static int wpa_config_parse_eap(const struct parse_data *data,
   1283 				struct wpa_ssid *ssid, int line,
   1284 				const char *value)
   1285 {
   1286 	int last, errors = 0;
   1287 	char *start, *end, *buf;
   1288 	struct eap_method_type *methods = NULL, *tmp;
   1289 	size_t num_methods = 0;
   1290 
   1291 	buf = os_strdup(value);
   1292 	if (buf == NULL)
   1293 		return -1;
   1294 	start = buf;
   1295 
   1296 	while (*start != '\0') {
   1297 		while (*start == ' ' || *start == '\t')
   1298 			start++;
   1299 		if (*start == '\0')
   1300 			break;
   1301 		end = start;
   1302 		while (*end != ' ' && *end != '\t' && *end != '\0')
   1303 			end++;
   1304 		last = *end == '\0';
   1305 		*end = '\0';
   1306 		tmp = methods;
   1307 		methods = os_realloc_array(methods, num_methods + 1,
   1308 					   sizeof(*methods));
   1309 		if (methods == NULL) {
   1310 			os_free(tmp);
   1311 			os_free(buf);
   1312 			return -1;
   1313 		}
   1314 		methods[num_methods].method = eap_peer_get_type(
   1315 			start, &methods[num_methods].vendor);
   1316 		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
   1317 		    methods[num_methods].method == EAP_TYPE_NONE) {
   1318 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
   1319 				   "'%s'", line, start);
   1320 			wpa_printf(MSG_ERROR, "You may need to add support for"
   1321 				   " this EAP method during wpa_supplicant\n"
   1322 				   "build time configuration.\n"
   1323 				   "See README for more information.");
   1324 			errors++;
   1325 		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
   1326 			   methods[num_methods].method == EAP_TYPE_LEAP)
   1327 			ssid->leap++;
   1328 		else
   1329 			ssid->non_leap++;
   1330 		num_methods++;
   1331 		if (last)
   1332 			break;
   1333 		start = end + 1;
   1334 	}
   1335 	os_free(buf);
   1336 
   1337 	tmp = methods;
   1338 	methods = os_realloc_array(methods, num_methods + 1, sizeof(*methods));
   1339 	if (methods == NULL) {
   1340 		os_free(tmp);
   1341 		return -1;
   1342 	}
   1343 	methods[num_methods].vendor = EAP_VENDOR_IETF;
   1344 	methods[num_methods].method = EAP_TYPE_NONE;
   1345 	num_methods++;
   1346 
   1347 	if (!errors && ssid->eap.eap_methods) {
   1348 		struct eap_method_type *prev_m;
   1349 		size_t i, j, prev_methods, match = 0;
   1350 
   1351 		prev_m = ssid->eap.eap_methods;
   1352 		for (i = 0; prev_m[i].vendor != EAP_VENDOR_IETF ||
   1353 			     prev_m[i].method != EAP_TYPE_NONE; i++) {
   1354 			/* Count the methods */
   1355 		}
   1356 		prev_methods = i + 1;
   1357 
   1358 		for (i = 0; prev_methods == num_methods && i < prev_methods;
   1359 		     i++) {
   1360 			for (j = 0; j < num_methods; j++) {
   1361 				if (prev_m[i].vendor == methods[j].vendor &&
   1362 				    prev_m[i].method == methods[j].method) {
   1363 					match++;
   1364 					break;
   1365 				}
   1366 			}
   1367 		}
   1368 		if (match == num_methods) {
   1369 			os_free(methods);
   1370 			return 1;
   1371 		}
   1372 	}
   1373 	wpa_hexdump(MSG_MSGDUMP, "eap methods",
   1374 		    (u8 *) methods, num_methods * sizeof(*methods));
   1375 	os_free(ssid->eap.eap_methods);
   1376 	ssid->eap.eap_methods = methods;
   1377 	return errors ? -1 : 0;
   1378 }
   1379 
   1380 
   1381 #ifndef NO_CONFIG_WRITE
   1382 static char * wpa_config_write_eap(const struct parse_data *data,
   1383 				   struct wpa_ssid *ssid)
   1384 {
   1385 	int i, ret;
   1386 	char *buf, *pos, *end;
   1387 	const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
   1388 	const char *name;
   1389 
   1390 	if (eap_methods == NULL)
   1391 		return NULL;
   1392 
   1393 	pos = buf = os_zalloc(100);
   1394 	if (buf == NULL)
   1395 		return NULL;
   1396 	end = buf + 100;
   1397 
   1398 	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
   1399 		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
   1400 		name = eap_get_name(eap_methods[i].vendor,
   1401 				    eap_methods[i].method);
   1402 		if (name) {
   1403 			ret = os_snprintf(pos, end - pos, "%s%s",
   1404 					  pos == buf ? "" : " ", name);
   1405 			if (os_snprintf_error(end - pos, ret))
   1406 				break;
   1407 			pos += ret;
   1408 		}
   1409 	}
   1410 
   1411 	end[-1] = '\0';
   1412 
   1413 	return buf;
   1414 }
   1415 #endif /* NO_CONFIG_WRITE */
   1416 
   1417 
   1418 static int wpa_config_parse_password(const struct parse_data *data,
   1419 				     struct wpa_ssid *ssid, int line,
   1420 				     const char *value)
   1421 {
   1422 	u8 *hash;
   1423 
   1424 	if (os_strcmp(value, "NULL") == 0) {
   1425 		if (!ssid->eap.password)
   1426 			return 1; /* Already unset */
   1427 		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
   1428 		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1429 		ssid->eap.password = NULL;
   1430 		ssid->eap.password_len = 0;
   1431 		return 0;
   1432 	}
   1433 
   1434 #ifdef CONFIG_EXT_PASSWORD
   1435 	if (os_strncmp(value, "ext:", 4) == 0) {
   1436 		char *name = os_strdup(value + 4);
   1437 		if (name == NULL)
   1438 			return -1;
   1439 		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1440 		ssid->eap.password = (u8 *) name;
   1441 		ssid->eap.password_len = os_strlen(name);
   1442 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1443 		ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1444 		return 0;
   1445 	}
   1446 #endif /* CONFIG_EXT_PASSWORD */
   1447 
   1448 	if (os_strncmp(value, "hash:", 5) != 0) {
   1449 		char *tmp;
   1450 		size_t res_len;
   1451 
   1452 		tmp = wpa_config_parse_string(value, &res_len);
   1453 		if (tmp == NULL) {
   1454 			wpa_printf(MSG_ERROR, "Line %d: failed to parse "
   1455 				   "password.", line);
   1456 			return -1;
   1457 		}
   1458 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
   1459 				      (u8 *) tmp, res_len);
   1460 
   1461 		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1462 		ssid->eap.password = (u8 *) tmp;
   1463 		ssid->eap.password_len = res_len;
   1464 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1465 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1466 
   1467 		return 0;
   1468 	}
   1469 
   1470 
   1471 	/* NtPasswordHash: hash:<32 hex digits> */
   1472 	if (os_strlen(value + 5) != 2 * 16) {
   1473 		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
   1474 			   "(expected 32 hex digits)", line);
   1475 		return -1;
   1476 	}
   1477 
   1478 	hash = os_malloc(16);
   1479 	if (hash == NULL)
   1480 		return -1;
   1481 
   1482 	if (hexstr2bin(value + 5, hash, 16)) {
   1483 		os_free(hash);
   1484 		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
   1485 		return -1;
   1486 	}
   1487 
   1488 	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
   1489 
   1490 	if (ssid->eap.password && ssid->eap.password_len == 16 &&
   1491 	    os_memcmp(ssid->eap.password, hash, 16) == 0 &&
   1492 	    (ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
   1493 		bin_clear_free(hash, 16);
   1494 		return 1;
   1495 	}
   1496 	bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1497 	ssid->eap.password = hash;
   1498 	ssid->eap.password_len = 16;
   1499 	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1500 	ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1501 
   1502 	return 0;
   1503 }
   1504 
   1505 
   1506 #ifndef NO_CONFIG_WRITE
   1507 static char * wpa_config_write_password(const struct parse_data *data,
   1508 					struct wpa_ssid *ssid)
   1509 {
   1510 	char *buf;
   1511 
   1512 	if (ssid->eap.password == NULL)
   1513 		return NULL;
   1514 
   1515 #ifdef CONFIG_EXT_PASSWORD
   1516 	if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
   1517 		buf = os_zalloc(4 + ssid->eap.password_len + 1);
   1518 		if (buf == NULL)
   1519 			return NULL;
   1520 		os_memcpy(buf, "ext:", 4);
   1521 		os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
   1522 		return buf;
   1523 	}
   1524 #endif /* CONFIG_EXT_PASSWORD */
   1525 
   1526 	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
   1527 		return wpa_config_write_string(
   1528 			ssid->eap.password, ssid->eap.password_len);
   1529 	}
   1530 
   1531 	buf = os_malloc(5 + 32 + 1);
   1532 	if (buf == NULL)
   1533 		return NULL;
   1534 
   1535 	os_memcpy(buf, "hash:", 5);
   1536 	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
   1537 
   1538 	return buf;
   1539 }
   1540 #endif /* NO_CONFIG_WRITE */
   1541 #endif /* IEEE8021X_EAPOL */
   1542 
   1543 
   1544 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
   1545 				    const char *value, int idx)
   1546 {
   1547 	char *buf, title[20];
   1548 	int res;
   1549 
   1550 	buf = wpa_config_parse_string(value, len);
   1551 	if (buf == NULL) {
   1552 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
   1553 			   line, idx, value);
   1554 		return -1;
   1555 	}
   1556 	if (*len > MAX_WEP_KEY_LEN) {
   1557 		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
   1558 			   line, idx, value);
   1559 		os_free(buf);
   1560 		return -1;
   1561 	}
   1562 	if (*len && *len != 5 && *len != 13 && *len != 16) {
   1563 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - "
   1564 			   "this network block will be ignored",
   1565 			   line, (unsigned int) *len);
   1566 	}
   1567 	os_memcpy(key, buf, *len);
   1568 	str_clear_free(buf);
   1569 	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
   1570 	if (!os_snprintf_error(sizeof(title), res))
   1571 		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
   1572 	return 0;
   1573 }
   1574 
   1575 
   1576 static int wpa_config_parse_wep_key0(const struct parse_data *data,
   1577 				     struct wpa_ssid *ssid, int line,
   1578 				     const char *value)
   1579 {
   1580 	return wpa_config_parse_wep_key(ssid->wep_key[0],
   1581 					&ssid->wep_key_len[0], line,
   1582 					value, 0);
   1583 }
   1584 
   1585 
   1586 static int wpa_config_parse_wep_key1(const struct parse_data *data,
   1587 				     struct wpa_ssid *ssid, int line,
   1588 				     const char *value)
   1589 {
   1590 	return wpa_config_parse_wep_key(ssid->wep_key[1],
   1591 					&ssid->wep_key_len[1], line,
   1592 					value, 1);
   1593 }
   1594 
   1595 
   1596 static int wpa_config_parse_wep_key2(const struct parse_data *data,
   1597 				     struct wpa_ssid *ssid, int line,
   1598 				     const char *value)
   1599 {
   1600 	return wpa_config_parse_wep_key(ssid->wep_key[2],
   1601 					&ssid->wep_key_len[2], line,
   1602 					value, 2);
   1603 }
   1604 
   1605 
   1606 static int wpa_config_parse_wep_key3(const struct parse_data *data,
   1607 				     struct wpa_ssid *ssid, int line,
   1608 				     const char *value)
   1609 {
   1610 	return wpa_config_parse_wep_key(ssid->wep_key[3],
   1611 					&ssid->wep_key_len[3], line,
   1612 					value, 3);
   1613 }
   1614 
   1615 
   1616 #ifndef NO_CONFIG_WRITE
   1617 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
   1618 {
   1619 	if (ssid->wep_key_len[idx] == 0)
   1620 		return NULL;
   1621 	return wpa_config_write_string(ssid->wep_key[idx],
   1622 				       ssid->wep_key_len[idx]);
   1623 }
   1624 
   1625 
   1626 static char * wpa_config_write_wep_key0(const struct parse_data *data,
   1627 					struct wpa_ssid *ssid)
   1628 {
   1629 	return wpa_config_write_wep_key(ssid, 0);
   1630 }
   1631 
   1632 
   1633 static char * wpa_config_write_wep_key1(const struct parse_data *data,
   1634 					struct wpa_ssid *ssid)
   1635 {
   1636 	return wpa_config_write_wep_key(ssid, 1);
   1637 }
   1638 
   1639 
   1640 static char * wpa_config_write_wep_key2(const struct parse_data *data,
   1641 					struct wpa_ssid *ssid)
   1642 {
   1643 	return wpa_config_write_wep_key(ssid, 2);
   1644 }
   1645 
   1646 
   1647 static char * wpa_config_write_wep_key3(const struct parse_data *data,
   1648 					struct wpa_ssid *ssid)
   1649 {
   1650 	return wpa_config_write_wep_key(ssid, 3);
   1651 }
   1652 #endif /* NO_CONFIG_WRITE */
   1653 
   1654 
   1655 #ifdef CONFIG_P2P
   1656 
   1657 static int wpa_config_parse_go_p2p_dev_addr(const struct parse_data *data,
   1658 					    struct wpa_ssid *ssid, int line,
   1659 					    const char *value)
   1660 {
   1661 	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
   1662 	    os_strcmp(value, "any") == 0) {
   1663 		os_memset(ssid->go_p2p_dev_addr, 0, ETH_ALEN);
   1664 		wpa_printf(MSG_MSGDUMP, "GO P2P Device Address any");
   1665 		return 0;
   1666 	}
   1667 	if (hwaddr_aton(value, ssid->go_p2p_dev_addr)) {
   1668 		wpa_printf(MSG_ERROR, "Line %d: Invalid GO P2P Device Address '%s'.",
   1669 			   line, value);
   1670 		return -1;
   1671 	}
   1672 	ssid->bssid_set = 1;
   1673 	wpa_printf(MSG_MSGDUMP, "GO P2P Device Address " MACSTR,
   1674 		   MAC2STR(ssid->go_p2p_dev_addr));
   1675 	return 0;
   1676 }
   1677 
   1678 
   1679 #ifndef NO_CONFIG_WRITE
   1680 static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data,
   1681 					       struct wpa_ssid *ssid)
   1682 {
   1683 	char *value;
   1684 	int res;
   1685 
   1686 	if (is_zero_ether_addr(ssid->go_p2p_dev_addr))
   1687 		return NULL;
   1688 
   1689 	value = os_malloc(20);
   1690 	if (value == NULL)
   1691 		return NULL;
   1692 	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr));
   1693 	if (os_snprintf_error(20, res)) {
   1694 		os_free(value);
   1695 		return NULL;
   1696 	}
   1697 	value[20 - 1] = '\0';
   1698 	return value;
   1699 }
   1700 #endif /* NO_CONFIG_WRITE */
   1701 
   1702 
   1703 static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
   1704 					    struct wpa_ssid *ssid, int line,
   1705 					    const char *value)
   1706 {
   1707 	return wpa_config_parse_addr_list(data, line, value,
   1708 					  &ssid->p2p_client_list,
   1709 					  &ssid->num_p2p_clients,
   1710 					  "p2p_client_list", 0, 0);
   1711 }
   1712 
   1713 
   1714 #ifndef NO_CONFIG_WRITE
   1715 static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
   1716 					       struct wpa_ssid *ssid)
   1717 {
   1718 	return wpa_config_write_addr_list(data, ssid->p2p_client_list,
   1719 					  ssid->num_p2p_clients,
   1720 					  "p2p_client_list");
   1721 }
   1722 #endif /* NO_CONFIG_WRITE */
   1723 
   1724 
   1725 static int wpa_config_parse_psk_list(const struct parse_data *data,
   1726 				     struct wpa_ssid *ssid, int line,
   1727 				     const char *value)
   1728 {
   1729 	struct psk_list_entry *p;
   1730 	const char *pos;
   1731 
   1732 	p = os_zalloc(sizeof(*p));
   1733 	if (p == NULL)
   1734 		return -1;
   1735 
   1736 	pos = value;
   1737 	if (os_strncmp(pos, "P2P-", 4) == 0) {
   1738 		p->p2p = 1;
   1739 		pos += 4;
   1740 	}
   1741 
   1742 	if (hwaddr_aton(pos, p->addr)) {
   1743 		wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'",
   1744 			   line, pos);
   1745 		os_free(p);
   1746 		return -1;
   1747 	}
   1748 	pos += 17;
   1749 	if (*pos != '-') {
   1750 		wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'",
   1751 			   line, pos);
   1752 		os_free(p);
   1753 		return -1;
   1754 	}
   1755 	pos++;
   1756 
   1757 	if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') {
   1758 		wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'",
   1759 			   line, pos);
   1760 		os_free(p);
   1761 		return -1;
   1762 	}
   1763 
   1764 	dl_list_add(&ssid->psk_list, &p->list);
   1765 
   1766 	return 0;
   1767 }
   1768 
   1769 
   1770 #ifndef NO_CONFIG_WRITE
   1771 static char * wpa_config_write_psk_list(const struct parse_data *data,
   1772 					struct wpa_ssid *ssid)
   1773 {
   1774 	return NULL;
   1775 }
   1776 #endif /* NO_CONFIG_WRITE */
   1777 
   1778 #endif /* CONFIG_P2P */
   1779 
   1780 
   1781 #ifdef CONFIG_MESH
   1782 
   1783 static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data,
   1784 					     struct wpa_ssid *ssid, int line,
   1785 					     const char *value)
   1786 {
   1787 	int *rates = wpa_config_parse_int_array(value);
   1788 
   1789 	if (rates == NULL) {
   1790 		wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'",
   1791 			   line, value);
   1792 		return -1;
   1793 	}
   1794 	if (rates[0] == 0) {
   1795 		os_free(rates);
   1796 		rates = NULL;
   1797 	}
   1798 
   1799 	os_free(ssid->mesh_basic_rates);
   1800 	ssid->mesh_basic_rates = rates;
   1801 
   1802 	return 0;
   1803 }
   1804 
   1805 
   1806 #ifndef NO_CONFIG_WRITE
   1807 
   1808 static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
   1809 						struct wpa_ssid *ssid)
   1810 {
   1811 	return wpa_config_write_freqs(data, ssid->mesh_basic_rates);
   1812 }
   1813 
   1814 #endif /* NO_CONFIG_WRITE */
   1815 
   1816 #endif /* CONFIG_MESH */
   1817 
   1818 
   1819 /* Helper macros for network block parser */
   1820 
   1821 #ifdef OFFSET
   1822 #undef OFFSET
   1823 #endif /* OFFSET */
   1824 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
   1825 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
   1826 
   1827 /* STR: Define a string variable for an ASCII string; f = field name */
   1828 #ifdef NO_CONFIG_WRITE
   1829 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
   1830 #define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
   1831 #else /* NO_CONFIG_WRITE */
   1832 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
   1833 #define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
   1834 #endif /* NO_CONFIG_WRITE */
   1835 #define STR(f) _STR(f), NULL, NULL, NULL, 0
   1836 #define STRe(f) _STRe(f), NULL, NULL, NULL, 0
   1837 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
   1838 #define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
   1839 
   1840 /* STR_LEN: Define a string variable with a separate variable for storing the
   1841  * data length. Unlike STR(), this can be used to store arbitrary binary data
   1842  * (i.e., even nul termination character). */
   1843 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
   1844 #define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
   1845 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
   1846 #define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
   1847 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
   1848 
   1849 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
   1850  * explicitly specified. */
   1851 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
   1852 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
   1853 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
   1854 
   1855 #ifdef NO_CONFIG_WRITE
   1856 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
   1857 #define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
   1858 #else /* NO_CONFIG_WRITE */
   1859 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
   1860 	OFFSET(f), (void *) 0
   1861 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
   1862 	OFFSET(eap.f), (void *) 0
   1863 #endif /* NO_CONFIG_WRITE */
   1864 
   1865 /* INT: Define an integer variable */
   1866 #define INT(f) _INT(f), NULL, NULL, 0
   1867 #define INTe(f) _INTe(f), NULL, NULL, 0
   1868 
   1869 /* INT_RANGE: Define an integer variable with allowed value range */
   1870 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
   1871 
   1872 /* FUNC: Define a configuration variable that uses a custom function for
   1873  * parsing and writing the value. */
   1874 #ifdef NO_CONFIG_WRITE
   1875 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
   1876 #else /* NO_CONFIG_WRITE */
   1877 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
   1878 	NULL, NULL, NULL, NULL
   1879 #endif /* NO_CONFIG_WRITE */
   1880 #define FUNC(f) _FUNC(f), 0
   1881 #define FUNC_KEY(f) _FUNC(f), 1
   1882 
   1883 /*
   1884  * Table of network configuration variables. This table is used to parse each
   1885  * network configuration variable, e.g., each line in wpa_supplicant.conf file
   1886  * that is inside a network block.
   1887  *
   1888  * This table is generated using the helper macros defined above and with
   1889  * generous help from the C pre-processor. The field name is stored as a string
   1890  * into .name and for STR and INT types, the offset of the target buffer within
   1891  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
   1892  * offset to the field containing the length of the configuration variable.
   1893  * .param3 and .param4 can be used to mark the allowed range (length for STR
   1894  * and value for INT).
   1895  *
   1896  * For each configuration line in wpa_supplicant.conf, the parser goes through
   1897  * this table and select the entry that matches with the field name. The parser
   1898  * function (.parser) is then called to parse the actual value of the field.
   1899  *
   1900  * This kind of mechanism makes it easy to add new configuration parameters,
   1901  * since only one line needs to be added into this table and into the
   1902  * struct wpa_ssid definition if the new variable is either a string or
   1903  * integer. More complex types will need to use their own parser and writer
   1904  * functions.
   1905  */
   1906 static const struct parse_data ssid_fields[] = {
   1907 	{ STR_RANGE(ssid, 0, SSID_MAX_LEN) },
   1908 	{ INT_RANGE(scan_ssid, 0, 1) },
   1909 	{ FUNC(bssid) },
   1910 	{ FUNC(bssid_blacklist) },
   1911 	{ FUNC(bssid_whitelist) },
   1912 	{ FUNC_KEY(psk) },
   1913 	{ INT(mem_only_psk) },
   1914 	{ FUNC(proto) },
   1915 	{ FUNC(key_mgmt) },
   1916 	{ INT(bg_scan_period) },
   1917 	{ FUNC(pairwise) },
   1918 	{ FUNC(group) },
   1919 	{ FUNC(auth_alg) },
   1920 	{ FUNC(scan_freq) },
   1921 	{ FUNC(freq_list) },
   1922 	{ INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT,
   1923 		    VHT_CHANWIDTH_80P80MHZ) },
   1924 #ifdef IEEE8021X_EAPOL
   1925 	{ FUNC(eap) },
   1926 	{ STR_LENe(identity) },
   1927 	{ STR_LENe(anonymous_identity) },
   1928 	{ FUNC_KEY(password) },
   1929 	{ STRe(ca_cert) },
   1930 	{ STRe(ca_path) },
   1931 	{ STRe(client_cert) },
   1932 	{ STRe(private_key) },
   1933 	{ STR_KEYe(private_key_passwd) },
   1934 	{ STRe(dh_file) },
   1935 	{ STRe(subject_match) },
   1936 	{ STRe(altsubject_match) },
   1937 	{ STRe(domain_suffix_match) },
   1938 	{ STRe(domain_match) },
   1939 	{ STRe(ca_cert2) },
   1940 	{ STRe(ca_path2) },
   1941 	{ STRe(client_cert2) },
   1942 	{ STRe(private_key2) },
   1943 	{ STR_KEYe(private_key2_passwd) },
   1944 	{ STRe(dh_file2) },
   1945 	{ STRe(subject_match2) },
   1946 	{ STRe(altsubject_match2) },
   1947 	{ STRe(domain_suffix_match2) },
   1948 	{ STRe(domain_match2) },
   1949 	{ STRe(phase1) },
   1950 	{ STRe(phase2) },
   1951 	{ STRe(pcsc) },
   1952 	{ STR_KEYe(pin) },
   1953 	{ STRe(engine_id) },
   1954 	{ STRe(key_id) },
   1955 	{ STRe(cert_id) },
   1956 	{ STRe(ca_cert_id) },
   1957 	{ STR_KEYe(pin2) },
   1958 	{ STRe(engine2_id) },
   1959 	{ STRe(key2_id) },
   1960 	{ STRe(cert2_id) },
   1961 	{ STRe(ca_cert2_id) },
   1962 	{ INTe(engine) },
   1963 	{ INTe(engine2) },
   1964 	{ INT(eapol_flags) },
   1965 	{ INTe(sim_num) },
   1966 	{ STRe(openssl_ciphers) },
   1967 	{ INTe(erp) },
   1968 #endif /* IEEE8021X_EAPOL */
   1969 	{ FUNC_KEY(wep_key0) },
   1970 	{ FUNC_KEY(wep_key1) },
   1971 	{ FUNC_KEY(wep_key2) },
   1972 	{ FUNC_KEY(wep_key3) },
   1973 	{ INT(wep_tx_keyidx) },
   1974 	{ INT(priority) },
   1975 #ifdef IEEE8021X_EAPOL
   1976 	{ INT(eap_workaround) },
   1977 	{ STRe(pac_file) },
   1978 	{ INTe(fragment_size) },
   1979 	{ INTe(ocsp) },
   1980 #endif /* IEEE8021X_EAPOL */
   1981 #ifdef CONFIG_MESH
   1982 	{ INT_RANGE(mode, 0, 5) },
   1983 	{ INT_RANGE(no_auto_peer, 0, 1) },
   1984 #else /* CONFIG_MESH */
   1985 	{ INT_RANGE(mode, 0, 4) },
   1986 #endif /* CONFIG_MESH */
   1987 	{ INT_RANGE(proactive_key_caching, 0, 1) },
   1988 	{ INT_RANGE(disabled, 0, 2) },
   1989 	{ STR(id_str) },
   1990 #ifdef CONFIG_IEEE80211W
   1991 	{ INT_RANGE(ieee80211w, 0, 2) },
   1992 #endif /* CONFIG_IEEE80211W */
   1993 	{ INT_RANGE(peerkey, 0, 1) },
   1994 	{ INT_RANGE(mixed_cell, 0, 1) },
   1995 	{ INT_RANGE(frequency, 0, 65000) },
   1996 	{ INT_RANGE(fixed_freq, 0, 1) },
   1997 #ifdef CONFIG_ACS
   1998 	{ INT_RANGE(acs, 0, 1) },
   1999 #endif /* CONFIG_ACS */
   2000 #ifdef CONFIG_MESH
   2001 	{ FUNC(mesh_basic_rates) },
   2002 	{ INT(dot11MeshMaxRetries) },
   2003 	{ INT(dot11MeshRetryTimeout) },
   2004 	{ INT(dot11MeshConfirmTimeout) },
   2005 	{ INT(dot11MeshHoldingTimeout) },
   2006 #endif /* CONFIG_MESH */
   2007 	{ INT(wpa_ptk_rekey) },
   2008 	{ INT(group_rekey) },
   2009 	{ STR(bgscan) },
   2010 	{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
   2011 #ifdef CONFIG_P2P
   2012 	{ FUNC(go_p2p_dev_addr) },
   2013 	{ FUNC(p2p_client_list) },
   2014 	{ FUNC(psk_list) },
   2015 #endif /* CONFIG_P2P */
   2016 #ifdef CONFIG_HT_OVERRIDES
   2017 	{ INT_RANGE(disable_ht, 0, 1) },
   2018 	{ INT_RANGE(disable_ht40, -1, 1) },
   2019 	{ INT_RANGE(disable_sgi, 0, 1) },
   2020 	{ INT_RANGE(disable_ldpc, 0, 1) },
   2021 	{ INT_RANGE(ht40_intolerant, 0, 1) },
   2022 	{ INT_RANGE(disable_max_amsdu, -1, 1) },
   2023 	{ INT_RANGE(ampdu_factor, -1, 3) },
   2024 	{ INT_RANGE(ampdu_density, -1, 7) },
   2025 	{ STR(ht_mcs) },
   2026 #endif /* CONFIG_HT_OVERRIDES */
   2027 #ifdef CONFIG_VHT_OVERRIDES
   2028 	{ INT_RANGE(disable_vht, 0, 1) },
   2029 	{ INT(vht_capa) },
   2030 	{ INT(vht_capa_mask) },
   2031 	{ INT_RANGE(vht_rx_mcs_nss_1, -1, 3) },
   2032 	{ INT_RANGE(vht_rx_mcs_nss_2, -1, 3) },
   2033 	{ INT_RANGE(vht_rx_mcs_nss_3, -1, 3) },
   2034 	{ INT_RANGE(vht_rx_mcs_nss_4, -1, 3) },
   2035 	{ INT_RANGE(vht_rx_mcs_nss_5, -1, 3) },
   2036 	{ INT_RANGE(vht_rx_mcs_nss_6, -1, 3) },
   2037 	{ INT_RANGE(vht_rx_mcs_nss_7, -1, 3) },
   2038 	{ INT_RANGE(vht_rx_mcs_nss_8, -1, 3) },
   2039 	{ INT_RANGE(vht_tx_mcs_nss_1, -1, 3) },
   2040 	{ INT_RANGE(vht_tx_mcs_nss_2, -1, 3) },
   2041 	{ INT_RANGE(vht_tx_mcs_nss_3, -1, 3) },
   2042 	{ INT_RANGE(vht_tx_mcs_nss_4, -1, 3) },
   2043 	{ INT_RANGE(vht_tx_mcs_nss_5, -1, 3) },
   2044 	{ INT_RANGE(vht_tx_mcs_nss_6, -1, 3) },
   2045 	{ INT_RANGE(vht_tx_mcs_nss_7, -1, 3) },
   2046 	{ INT_RANGE(vht_tx_mcs_nss_8, -1, 3) },
   2047 #endif /* CONFIG_VHT_OVERRIDES */
   2048 	{ INT(ap_max_inactivity) },
   2049 	{ INT(dtim_period) },
   2050 	{ INT(beacon_int) },
   2051 #ifdef CONFIG_MACSEC
   2052 	{ INT_RANGE(macsec_policy, 0, 1) },
   2053 #endif /* CONFIG_MACSEC */
   2054 #ifdef CONFIG_HS20
   2055 	{ INT(update_identifier) },
   2056 #endif /* CONFIG_HS20 */
   2057 	{ INT_RANGE(mac_addr, 0, 2) },
   2058 	{ INT_RANGE(pbss, 0, 2) },
   2059 	{ INT_RANGE(wps_disabled, 0, 1) },
   2060 };
   2061 
   2062 #undef OFFSET
   2063 #undef _STR
   2064 #undef STR
   2065 #undef STR_KEY
   2066 #undef _STR_LEN
   2067 #undef STR_LEN
   2068 #undef STR_LEN_KEY
   2069 #undef _STR_RANGE
   2070 #undef STR_RANGE
   2071 #undef STR_RANGE_KEY
   2072 #undef _INT
   2073 #undef INT
   2074 #undef INT_RANGE
   2075 #undef _FUNC
   2076 #undef FUNC
   2077 #undef FUNC_KEY
   2078 #define NUM_SSID_FIELDS ARRAY_SIZE(ssid_fields)
   2079 
   2080 
   2081 /**
   2082  * wpa_config_add_prio_network - Add a network to priority lists
   2083  * @config: Configuration data from wpa_config_read()
   2084  * @ssid: Pointer to the network configuration to be added to the list
   2085  * Returns: 0 on success, -1 on failure
   2086  *
   2087  * This function is used to add a network block to the priority list of
   2088  * networks. This must be called for each network when reading in the full
   2089  * configuration. In addition, this can be used indirectly when updating
   2090  * priorities by calling wpa_config_update_prio_list().
   2091  */
   2092 int wpa_config_add_prio_network(struct wpa_config *config,
   2093 				struct wpa_ssid *ssid)
   2094 {
   2095 	int prio;
   2096 	struct wpa_ssid *prev, **nlist;
   2097 
   2098 	/*
   2099 	 * Add to an existing priority list if one is available for the
   2100 	 * configured priority level for this network.
   2101 	 */
   2102 	for (prio = 0; prio < config->num_prio; prio++) {
   2103 		prev = config->pssid[prio];
   2104 		if (prev->priority == ssid->priority) {
   2105 			while (prev->pnext)
   2106 				prev = prev->pnext;
   2107 			prev->pnext = ssid;
   2108 			return 0;
   2109 		}
   2110 	}
   2111 
   2112 	/* First network for this priority - add a new priority list */
   2113 	nlist = os_realloc_array(config->pssid, config->num_prio + 1,
   2114 				 sizeof(struct wpa_ssid *));
   2115 	if (nlist == NULL)
   2116 		return -1;
   2117 
   2118 	for (prio = 0; prio < config->num_prio; prio++) {
   2119 		if (nlist[prio]->priority < ssid->priority) {
   2120 			os_memmove(&nlist[prio + 1], &nlist[prio],
   2121 				   (config->num_prio - prio) *
   2122 				   sizeof(struct wpa_ssid *));
   2123 			break;
   2124 		}
   2125 	}
   2126 
   2127 	nlist[prio] = ssid;
   2128 	config->num_prio++;
   2129 	config->pssid = nlist;
   2130 
   2131 	return 0;
   2132 }
   2133 
   2134 
   2135 /**
   2136  * wpa_config_update_prio_list - Update network priority list
   2137  * @config: Configuration data from wpa_config_read()
   2138  * Returns: 0 on success, -1 on failure
   2139  *
   2140  * This function is called to update the priority list of networks in the
   2141  * configuration when a network is being added or removed. This is also called
   2142  * if a priority for a network is changed.
   2143  */
   2144 int wpa_config_update_prio_list(struct wpa_config *config)
   2145 {
   2146 	struct wpa_ssid *ssid;
   2147 	int ret = 0;
   2148 
   2149 	os_free(config->pssid);
   2150 	config->pssid = NULL;
   2151 	config->num_prio = 0;
   2152 
   2153 	ssid = config->ssid;
   2154 	while (ssid) {
   2155 		ssid->pnext = NULL;
   2156 		if (wpa_config_add_prio_network(config, ssid) < 0)
   2157 			ret = -1;
   2158 		ssid = ssid->next;
   2159 	}
   2160 
   2161 	return ret;
   2162 }
   2163 
   2164 
   2165 #ifdef IEEE8021X_EAPOL
   2166 static void eap_peer_config_free(struct eap_peer_config *eap)
   2167 {
   2168 	os_free(eap->eap_methods);
   2169 	bin_clear_free(eap->identity, eap->identity_len);
   2170 	os_free(eap->anonymous_identity);
   2171 	bin_clear_free(eap->password, eap->password_len);
   2172 	os_free(eap->ca_cert);
   2173 	os_free(eap->ca_path);
   2174 	os_free(eap->client_cert);
   2175 	os_free(eap->private_key);
   2176 	str_clear_free(eap->private_key_passwd);
   2177 	os_free(eap->dh_file);
   2178 	os_free(eap->subject_match);
   2179 	os_free(eap->altsubject_match);
   2180 	os_free(eap->domain_suffix_match);
   2181 	os_free(eap->domain_match);
   2182 	os_free(eap->ca_cert2);
   2183 	os_free(eap->ca_path2);
   2184 	os_free(eap->client_cert2);
   2185 	os_free(eap->private_key2);
   2186 	str_clear_free(eap->private_key2_passwd);
   2187 	os_free(eap->dh_file2);
   2188 	os_free(eap->subject_match2);
   2189 	os_free(eap->altsubject_match2);
   2190 	os_free(eap->domain_suffix_match2);
   2191 	os_free(eap->domain_match2);
   2192 	os_free(eap->phase1);
   2193 	os_free(eap->phase2);
   2194 	os_free(eap->pcsc);
   2195 	str_clear_free(eap->pin);
   2196 	os_free(eap->engine_id);
   2197 	os_free(eap->key_id);
   2198 	os_free(eap->cert_id);
   2199 	os_free(eap->ca_cert_id);
   2200 	os_free(eap->key2_id);
   2201 	os_free(eap->cert2_id);
   2202 	os_free(eap->ca_cert2_id);
   2203 	str_clear_free(eap->pin2);
   2204 	os_free(eap->engine2_id);
   2205 	os_free(eap->otp);
   2206 	os_free(eap->pending_req_otp);
   2207 	os_free(eap->pac_file);
   2208 	bin_clear_free(eap->new_password, eap->new_password_len);
   2209 	str_clear_free(eap->external_sim_resp);
   2210 	os_free(eap->openssl_ciphers);
   2211 }
   2212 #endif /* IEEE8021X_EAPOL */
   2213 
   2214 
   2215 /**
   2216  * wpa_config_free_ssid - Free network/ssid configuration data
   2217  * @ssid: Configuration data for the network
   2218  *
   2219  * This function frees all resources allocated for the network configuration
   2220  * data.
   2221  */
   2222 void wpa_config_free_ssid(struct wpa_ssid *ssid)
   2223 {
   2224 	struct psk_list_entry *psk;
   2225 
   2226 	os_free(ssid->ssid);
   2227 	str_clear_free(ssid->passphrase);
   2228 	os_free(ssid->ext_psk);
   2229 #ifdef IEEE8021X_EAPOL
   2230 	eap_peer_config_free(&ssid->eap);
   2231 #endif /* IEEE8021X_EAPOL */
   2232 	os_free(ssid->id_str);
   2233 	os_free(ssid->scan_freq);
   2234 	os_free(ssid->freq_list);
   2235 	os_free(ssid->bgscan);
   2236 	os_free(ssid->p2p_client_list);
   2237 	os_free(ssid->bssid_blacklist);
   2238 	os_free(ssid->bssid_whitelist);
   2239 #ifdef CONFIG_HT_OVERRIDES
   2240 	os_free(ssid->ht_mcs);
   2241 #endif /* CONFIG_HT_OVERRIDES */
   2242 #ifdef CONFIG_MESH
   2243 	os_free(ssid->mesh_basic_rates);
   2244 #endif /* CONFIG_MESH */
   2245 	while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
   2246 				    list))) {
   2247 		dl_list_del(&psk->list);
   2248 		bin_clear_free(psk, sizeof(*psk));
   2249 	}
   2250 	bin_clear_free(ssid, sizeof(*ssid));
   2251 }
   2252 
   2253 
   2254 void wpa_config_free_cred(struct wpa_cred *cred)
   2255 {
   2256 	size_t i;
   2257 
   2258 	os_free(cred->realm);
   2259 	str_clear_free(cred->username);
   2260 	str_clear_free(cred->password);
   2261 	os_free(cred->ca_cert);
   2262 	os_free(cred->client_cert);
   2263 	os_free(cred->private_key);
   2264 	str_clear_free(cred->private_key_passwd);
   2265 	os_free(cred->imsi);
   2266 	str_clear_free(cred->milenage);
   2267 	for (i = 0; i < cred->num_domain; i++)
   2268 		os_free(cred->domain[i]);
   2269 	os_free(cred->domain);
   2270 	os_free(cred->domain_suffix_match);
   2271 	os_free(cred->eap_method);
   2272 	os_free(cred->phase1);
   2273 	os_free(cred->phase2);
   2274 	os_free(cred->excluded_ssid);
   2275 	os_free(cred->roaming_partner);
   2276 	os_free(cred->provisioning_sp);
   2277 	for (i = 0; i < cred->num_req_conn_capab; i++)
   2278 		os_free(cred->req_conn_capab_port[i]);
   2279 	os_free(cred->req_conn_capab_port);
   2280 	os_free(cred->req_conn_capab_proto);
   2281 	os_free(cred);
   2282 }
   2283 
   2284 
   2285 void wpa_config_flush_blobs(struct wpa_config *config)
   2286 {
   2287 #ifndef CONFIG_NO_CONFIG_BLOBS
   2288 	struct wpa_config_blob *blob, *prev;
   2289 
   2290 	blob = config->blobs;
   2291 	config->blobs = NULL;
   2292 	while (blob) {
   2293 		prev = blob;
   2294 		blob = blob->next;
   2295 		wpa_config_free_blob(prev);
   2296 	}
   2297 #endif /* CONFIG_NO_CONFIG_BLOBS */
   2298 }
   2299 
   2300 
   2301 /**
   2302  * wpa_config_free - Free configuration data
   2303  * @config: Configuration data from wpa_config_read()
   2304  *
   2305  * This function frees all resources allocated for the configuration data by
   2306  * wpa_config_read().
   2307  */
   2308 void wpa_config_free(struct wpa_config *config)
   2309 {
   2310 	struct wpa_ssid *ssid, *prev = NULL;
   2311 	struct wpa_cred *cred, *cprev;
   2312 	int i;
   2313 
   2314 	ssid = config->ssid;
   2315 	while (ssid) {
   2316 		prev = ssid;
   2317 		ssid = ssid->next;
   2318 		wpa_config_free_ssid(prev);
   2319 	}
   2320 
   2321 	cred = config->cred;
   2322 	while (cred) {
   2323 		cprev = cred;
   2324 		cred = cred->next;
   2325 		wpa_config_free_cred(cprev);
   2326 	}
   2327 
   2328 	wpa_config_flush_blobs(config);
   2329 
   2330 	wpabuf_free(config->wps_vendor_ext_m1);
   2331 	for (i = 0; i < MAX_WPS_VENDOR_EXT; i++)
   2332 		wpabuf_free(config->wps_vendor_ext[i]);
   2333 	os_free(config->ctrl_interface);
   2334 	os_free(config->ctrl_interface_group);
   2335 	os_free(config->opensc_engine_path);
   2336 	os_free(config->pkcs11_engine_path);
   2337 	os_free(config->pkcs11_module_path);
   2338 	os_free(config->openssl_ciphers);
   2339 	os_free(config->pcsc_reader);
   2340 	str_clear_free(config->pcsc_pin);
   2341 	os_free(config->driver_param);
   2342 	os_free(config->device_name);
   2343 	os_free(config->manufacturer);
   2344 	os_free(config->model_name);
   2345 	os_free(config->model_number);
   2346 	os_free(config->serial_number);
   2347 	os_free(config->config_methods);
   2348 	os_free(config->p2p_ssid_postfix);
   2349 	os_free(config->pssid);
   2350 	os_free(config->p2p_pref_chan);
   2351 	os_free(config->p2p_no_go_freq.range);
   2352 	os_free(config->autoscan);
   2353 	os_free(config->freq_list);
   2354 	wpabuf_free(config->wps_nfc_dh_pubkey);
   2355 	wpabuf_free(config->wps_nfc_dh_privkey);
   2356 	wpabuf_free(config->wps_nfc_dev_pw);
   2357 	os_free(config->ext_password_backend);
   2358 	os_free(config->sae_groups);
   2359 	wpabuf_free(config->ap_vendor_elements);
   2360 	os_free(config->osu_dir);
   2361 	os_free(config->bgscan);
   2362 	os_free(config->wowlan_triggers);
   2363 	os_free(config->fst_group_id);
   2364 	os_free(config->sched_scan_plans);
   2365 #ifdef CONFIG_MBO
   2366 	os_free(config->non_pref_chan);
   2367 #endif /* CONFIG_MBO */
   2368 
   2369 	os_free(config);
   2370 }
   2371 
   2372 
   2373 /**
   2374  * wpa_config_foreach_network - Iterate over each configured network
   2375  * @config: Configuration data from wpa_config_read()
   2376  * @func: Callback function to process each network
   2377  * @arg: Opaque argument to pass to callback function
   2378  *
   2379  * Iterate over the set of configured networks calling the specified
   2380  * function for each item. We guard against callbacks removing the
   2381  * supplied network.
   2382  */
   2383 void wpa_config_foreach_network(struct wpa_config *config,
   2384 				void (*func)(void *, struct wpa_ssid *),
   2385 				void *arg)
   2386 {
   2387 	struct wpa_ssid *ssid, *next;
   2388 
   2389 	ssid = config->ssid;
   2390 	while (ssid) {
   2391 		next = ssid->next;
   2392 		func(arg, ssid);
   2393 		ssid = next;
   2394 	}
   2395 }
   2396 
   2397 
   2398 /**
   2399  * wpa_config_get_network - Get configured network based on id
   2400  * @config: Configuration data from wpa_config_read()
   2401  * @id: Unique network id to search for
   2402  * Returns: Network configuration or %NULL if not found
   2403  */
   2404 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
   2405 {
   2406 	struct wpa_ssid *ssid;
   2407 
   2408 	ssid = config->ssid;
   2409 	while (ssid) {
   2410 		if (id == ssid->id)
   2411 			break;
   2412 		ssid = ssid->next;
   2413 	}
   2414 
   2415 	return ssid;
   2416 }
   2417 
   2418 
   2419 /**
   2420  * wpa_config_add_network - Add a new network with empty configuration
   2421  * @config: Configuration data from wpa_config_read()
   2422  * Returns: The new network configuration or %NULL if operation failed
   2423  */
   2424 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
   2425 {
   2426 	int id;
   2427 	struct wpa_ssid *ssid, *last = NULL;
   2428 
   2429 	id = -1;
   2430 	ssid = config->ssid;
   2431 	while (ssid) {
   2432 		if (ssid->id > id)
   2433 			id = ssid->id;
   2434 		last = ssid;
   2435 		ssid = ssid->next;
   2436 	}
   2437 	id++;
   2438 
   2439 	ssid = os_zalloc(sizeof(*ssid));
   2440 	if (ssid == NULL)
   2441 		return NULL;
   2442 	ssid->id = id;
   2443 	dl_list_init(&ssid->psk_list);
   2444 	if (last)
   2445 		last->next = ssid;
   2446 	else
   2447 		config->ssid = ssid;
   2448 
   2449 	wpa_config_update_prio_list(config);
   2450 
   2451 	return ssid;
   2452 }
   2453 
   2454 
   2455 /**
   2456  * wpa_config_remove_network - Remove a configured network based on id
   2457  * @config: Configuration data from wpa_config_read()
   2458  * @id: Unique network id to search for
   2459  * Returns: 0 on success, or -1 if the network was not found
   2460  */
   2461 int wpa_config_remove_network(struct wpa_config *config, int id)
   2462 {
   2463 	struct wpa_ssid *ssid, *prev = NULL;
   2464 
   2465 	ssid = config->ssid;
   2466 	while (ssid) {
   2467 		if (id == ssid->id)
   2468 			break;
   2469 		prev = ssid;
   2470 		ssid = ssid->next;
   2471 	}
   2472 
   2473 	if (ssid == NULL)
   2474 		return -1;
   2475 
   2476 	if (prev)
   2477 		prev->next = ssid->next;
   2478 	else
   2479 		config->ssid = ssid->next;
   2480 
   2481 	wpa_config_update_prio_list(config);
   2482 	wpa_config_free_ssid(ssid);
   2483 	return 0;
   2484 }
   2485 
   2486 
   2487 /**
   2488  * wpa_config_set_network_defaults - Set network default values
   2489  * @ssid: Pointer to network configuration data
   2490  */
   2491 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
   2492 {
   2493 	ssid->proto = DEFAULT_PROTO;
   2494 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
   2495 	ssid->group_cipher = DEFAULT_GROUP;
   2496 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
   2497 	ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
   2498 #ifdef IEEE8021X_EAPOL
   2499 	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
   2500 	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
   2501 	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
   2502 	ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM;
   2503 #endif /* IEEE8021X_EAPOL */
   2504 #ifdef CONFIG_MESH
   2505 	ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES;
   2506 	ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
   2507 	ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
   2508 	ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
   2509 #endif /* CONFIG_MESH */
   2510 #ifdef CONFIG_HT_OVERRIDES
   2511 	ssid->disable_ht = DEFAULT_DISABLE_HT;
   2512 	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
   2513 	ssid->disable_sgi = DEFAULT_DISABLE_SGI;
   2514 	ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
   2515 	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
   2516 	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
   2517 	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
   2518 #endif /* CONFIG_HT_OVERRIDES */
   2519 #ifdef CONFIG_VHT_OVERRIDES
   2520 	ssid->vht_rx_mcs_nss_1 = -1;
   2521 	ssid->vht_rx_mcs_nss_2 = -1;
   2522 	ssid->vht_rx_mcs_nss_3 = -1;
   2523 	ssid->vht_rx_mcs_nss_4 = -1;
   2524 	ssid->vht_rx_mcs_nss_5 = -1;
   2525 	ssid->vht_rx_mcs_nss_6 = -1;
   2526 	ssid->vht_rx_mcs_nss_7 = -1;
   2527 	ssid->vht_rx_mcs_nss_8 = -1;
   2528 	ssid->vht_tx_mcs_nss_1 = -1;
   2529 	ssid->vht_tx_mcs_nss_2 = -1;
   2530 	ssid->vht_tx_mcs_nss_3 = -1;
   2531 	ssid->vht_tx_mcs_nss_4 = -1;
   2532 	ssid->vht_tx_mcs_nss_5 = -1;
   2533 	ssid->vht_tx_mcs_nss_6 = -1;
   2534 	ssid->vht_tx_mcs_nss_7 = -1;
   2535 	ssid->vht_tx_mcs_nss_8 = -1;
   2536 #endif /* CONFIG_VHT_OVERRIDES */
   2537 	ssid->proactive_key_caching = -1;
   2538 #ifdef CONFIG_IEEE80211W
   2539 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
   2540 #endif /* CONFIG_IEEE80211W */
   2541 	ssid->mac_addr = -1;
   2542 }
   2543 
   2544 
   2545 /**
   2546  * wpa_config_set - Set a variable in network configuration
   2547  * @ssid: Pointer to network configuration data
   2548  * @var: Variable name, e.g., "ssid"
   2549  * @value: Variable value
   2550  * @line: Line number in configuration file or 0 if not used
   2551  * Returns: 0 on success with possible change in the value, 1 on success with
   2552  * no change to previously configured value, or -1 on failure
   2553  *
   2554  * This function can be used to set network configuration variables based on
   2555  * both the configuration file and management interface input. The value
   2556  * parameter must be in the same format as the text-based configuration file is
   2557  * using. For example, strings are using double quotation marks.
   2558  */
   2559 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
   2560 		   int line)
   2561 {
   2562 	size_t i;
   2563 	int ret = 0;
   2564 
   2565 	if (ssid == NULL || var == NULL || value == NULL)
   2566 		return -1;
   2567 
   2568 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2569 		const struct parse_data *field = &ssid_fields[i];
   2570 		if (os_strcmp(var, field->name) != 0)
   2571 			continue;
   2572 
   2573 		ret = field->parser(field, ssid, line, value);
   2574 		if (ret < 0) {
   2575 			if (line) {
   2576 				wpa_printf(MSG_ERROR, "Line %d: failed to "
   2577 					   "parse %s '%s'.", line, var, value);
   2578 			}
   2579 			ret = -1;
   2580 		}
   2581 		break;
   2582 	}
   2583 	if (i == NUM_SSID_FIELDS) {
   2584 		if (line) {
   2585 			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
   2586 				   "'%s'.", line, var);
   2587 		}
   2588 		ret = -1;
   2589 	}
   2590 
   2591 	return ret;
   2592 }
   2593 
   2594 
   2595 int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
   2596 			  const char *value)
   2597 {
   2598 	size_t len;
   2599 	char *buf;
   2600 	int ret;
   2601 
   2602 	len = os_strlen(value);
   2603 	buf = os_malloc(len + 3);
   2604 	if (buf == NULL)
   2605 		return -1;
   2606 	buf[0] = '"';
   2607 	os_memcpy(buf + 1, value, len);
   2608 	buf[len + 1] = '"';
   2609 	buf[len + 2] = '\0';
   2610 	ret = wpa_config_set(ssid, var, buf, 0);
   2611 	os_free(buf);
   2612 	return ret;
   2613 }
   2614 
   2615 
   2616 /**
   2617  * wpa_config_get_all - Get all options from network configuration
   2618  * @ssid: Pointer to network configuration data
   2619  * @get_keys: Determines if keys/passwords will be included in returned list
   2620  *	(if they may be exported)
   2621  * Returns: %NULL terminated list of all set keys and their values in the form
   2622  * of [key1, val1, key2, val2, ... , NULL]
   2623  *
   2624  * This function can be used to get list of all configured network properties.
   2625  * The caller is responsible for freeing the returned list and all its
   2626  * elements.
   2627  */
   2628 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
   2629 {
   2630 #ifdef NO_CONFIG_WRITE
   2631 	return NULL;
   2632 #else /* NO_CONFIG_WRITE */
   2633 	const struct parse_data *field;
   2634 	char *key, *value;
   2635 	size_t i;
   2636 	char **props;
   2637 	int fields_num;
   2638 
   2639 	get_keys = get_keys && ssid->export_keys;
   2640 
   2641 	props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *));
   2642 	if (!props)
   2643 		return NULL;
   2644 
   2645 	fields_num = 0;
   2646 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2647 		field = &ssid_fields[i];
   2648 		if (field->key_data && !get_keys)
   2649 			continue;
   2650 		value = field->writer(field, ssid);
   2651 		if (value == NULL)
   2652 			continue;
   2653 		if (os_strlen(value) == 0) {
   2654 			os_free(value);
   2655 			continue;
   2656 		}
   2657 
   2658 		key = os_strdup(field->name);
   2659 		if (key == NULL) {
   2660 			os_free(value);
   2661 			goto err;
   2662 		}
   2663 
   2664 		props[fields_num * 2] = key;
   2665 		props[fields_num * 2 + 1] = value;
   2666 
   2667 		fields_num++;
   2668 	}
   2669 
   2670 	return props;
   2671 
   2672 err:
   2673 	for (i = 0; props[i]; i++)
   2674 		os_free(props[i]);
   2675 	os_free(props);
   2676 	return NULL;
   2677 #endif /* NO_CONFIG_WRITE */
   2678 }
   2679 
   2680 
   2681 #ifndef NO_CONFIG_WRITE
   2682 /**
   2683  * wpa_config_get - Get a variable in network configuration
   2684  * @ssid: Pointer to network configuration data
   2685  * @var: Variable name, e.g., "ssid"
   2686  * Returns: Value of the variable or %NULL on failure
   2687  *
   2688  * This function can be used to get network configuration variables. The
   2689  * returned value is a copy of the configuration variable in text format, i.e,.
   2690  * the same format that the text-based configuration file and wpa_config_set()
   2691  * are using for the value. The caller is responsible for freeing the returned
   2692  * value.
   2693  */
   2694 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
   2695 {
   2696 	size_t i;
   2697 
   2698 	if (ssid == NULL || var == NULL)
   2699 		return NULL;
   2700 
   2701 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2702 		const struct parse_data *field = &ssid_fields[i];
   2703 		if (os_strcmp(var, field->name) == 0) {
   2704 			char *ret = field->writer(field, ssid);
   2705 
   2706 			if (ret && has_newline(ret)) {
   2707 				wpa_printf(MSG_ERROR,
   2708 					   "Found newline in value for %s; not returning it",
   2709 					   var);
   2710 				os_free(ret);
   2711 				ret = NULL;
   2712 			}
   2713 
   2714 			return ret;
   2715 		}
   2716 	}
   2717 
   2718 	return NULL;
   2719 }
   2720 
   2721 
   2722 /**
   2723  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
   2724  * @ssid: Pointer to network configuration data
   2725  * @var: Variable name, e.g., "ssid"
   2726  * Returns: Value of the variable or %NULL on failure
   2727  *
   2728  * This function can be used to get network configuration variable like
   2729  * wpa_config_get(). The only difference is that this functions does not expose
   2730  * key/password material from the configuration. In case a key/password field
   2731  * is requested, the returned value is an empty string or %NULL if the variable
   2732  * is not set or "*" if the variable is set (regardless of its value). The
   2733  * returned value is a copy of the configuration variable in text format, i.e,.
   2734  * the same format that the text-based configuration file and wpa_config_set()
   2735  * are using for the value. The caller is responsible for freeing the returned
   2736  * value.
   2737  */
   2738 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
   2739 {
   2740 	size_t i;
   2741 
   2742 	if (ssid == NULL || var == NULL)
   2743 		return NULL;
   2744 
   2745 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2746 		const struct parse_data *field = &ssid_fields[i];
   2747 		if (os_strcmp(var, field->name) == 0) {
   2748 			char *res = field->writer(field, ssid);
   2749 			if (field->key_data) {
   2750 				if (res && res[0]) {
   2751 					wpa_printf(MSG_DEBUG, "Do not allow "
   2752 						   "key_data field to be "
   2753 						   "exposed");
   2754 					str_clear_free(res);
   2755 					return os_strdup("*");
   2756 				}
   2757 
   2758 				os_free(res);
   2759 				return NULL;
   2760 			}
   2761 			return res;
   2762 		}
   2763 	}
   2764 
   2765 	return NULL;
   2766 }
   2767 #endif /* NO_CONFIG_WRITE */
   2768 
   2769 
   2770 /**
   2771  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
   2772  * @ssid: Pointer to network configuration data
   2773  *
   2774  * This function must be called to update WPA PSK when either SSID or the
   2775  * passphrase has changed for the network configuration.
   2776  */
   2777 void wpa_config_update_psk(struct wpa_ssid *ssid)
   2778 {
   2779 #ifndef CONFIG_NO_PBKDF2
   2780 	pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096,
   2781 		    ssid->psk, PMK_LEN);
   2782 	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
   2783 			ssid->psk, PMK_LEN);
   2784 	ssid->psk_set = 1;
   2785 #endif /* CONFIG_NO_PBKDF2 */
   2786 }
   2787 
   2788 
   2789 static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred,
   2790 					      const char *value)
   2791 {
   2792 	u8 *proto;
   2793 	int **port;
   2794 	int *ports, *nports;
   2795 	const char *pos;
   2796 	unsigned int num_ports;
   2797 
   2798 	proto = os_realloc_array(cred->req_conn_capab_proto,
   2799 				 cred->num_req_conn_capab + 1, sizeof(u8));
   2800 	if (proto == NULL)
   2801 		return -1;
   2802 	cred->req_conn_capab_proto = proto;
   2803 
   2804 	port = os_realloc_array(cred->req_conn_capab_port,
   2805 				cred->num_req_conn_capab + 1, sizeof(int *));
   2806 	if (port == NULL)
   2807 		return -1;
   2808 	cred->req_conn_capab_port = port;
   2809 
   2810 	proto[cred->num_req_conn_capab] = atoi(value);
   2811 
   2812 	pos = os_strchr(value, ':');
   2813 	if (pos == NULL) {
   2814 		port[cred->num_req_conn_capab] = NULL;
   2815 		cred->num_req_conn_capab++;
   2816 		return 0;
   2817 	}
   2818 	pos++;
   2819 
   2820 	ports = NULL;
   2821 	num_ports = 0;
   2822 
   2823 	while (*pos) {
   2824 		nports = os_realloc_array(ports, num_ports + 1, sizeof(int));
   2825 		if (nports == NULL) {
   2826 			os_free(ports);
   2827 			return -1;
   2828 		}
   2829 		ports = nports;
   2830 		ports[num_ports++] = atoi(pos);
   2831 
   2832 		pos = os_strchr(pos, ',');
   2833 		if (pos == NULL)
   2834 			break;
   2835 		pos++;
   2836 	}
   2837 
   2838 	nports = os_realloc_array(ports, num_ports + 1, sizeof(int));
   2839 	if (nports == NULL) {
   2840 		os_free(ports);
   2841 		return -1;
   2842 	}
   2843 	ports = nports;
   2844 	ports[num_ports] = -1;
   2845 
   2846 	port[cred->num_req_conn_capab] = ports;
   2847 	cred->num_req_conn_capab++;
   2848 	return 0;
   2849 }
   2850 
   2851 
   2852 int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
   2853 			const char *value, int line)
   2854 {
   2855 	char *val;
   2856 	size_t len;
   2857 
   2858 	if (os_strcmp(var, "temporary") == 0) {
   2859 		cred->temporary = atoi(value);
   2860 		return 0;
   2861 	}
   2862 
   2863 	if (os_strcmp(var, "priority") == 0) {
   2864 		cred->priority = atoi(value);
   2865 		return 0;
   2866 	}
   2867 
   2868 	if (os_strcmp(var, "sp_priority") == 0) {
   2869 		int prio = atoi(value);
   2870 		if (prio < 0 || prio > 255)
   2871 			return -1;
   2872 		cred->sp_priority = prio;
   2873 		return 0;
   2874 	}
   2875 
   2876 	if (os_strcmp(var, "pcsc") == 0) {
   2877 		cred->pcsc = atoi(value);
   2878 		return 0;
   2879 	}
   2880 
   2881 	if (os_strcmp(var, "eap") == 0) {
   2882 		struct eap_method_type method;
   2883 		method.method = eap_peer_get_type(value, &method.vendor);
   2884 		if (method.vendor == EAP_VENDOR_IETF &&
   2885 		    method.method == EAP_TYPE_NONE) {
   2886 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' "
   2887 				   "for a credential", line, value);
   2888 			return -1;
   2889 		}
   2890 		os_free(cred->eap_method);
   2891 		cred->eap_method = os_malloc(sizeof(*cred->eap_method));
   2892 		if (cred->eap_method == NULL)
   2893 			return -1;
   2894 		os_memcpy(cred->eap_method, &method, sizeof(method));
   2895 		return 0;
   2896 	}
   2897 
   2898 	if (os_strcmp(var, "password") == 0 &&
   2899 	    os_strncmp(value, "ext:", 4) == 0) {
   2900 		if (has_newline(value))
   2901 			return -1;
   2902 		str_clear_free(cred->password);
   2903 		cred->password = os_strdup(value);
   2904 		cred->ext_password = 1;
   2905 		return 0;
   2906 	}
   2907 
   2908 	if (os_strcmp(var, "update_identifier") == 0) {
   2909 		cred->update_identifier = atoi(value);
   2910 		return 0;
   2911 	}
   2912 
   2913 	if (os_strcmp(var, "min_dl_bandwidth_home") == 0) {
   2914 		cred->min_dl_bandwidth_home = atoi(value);
   2915 		return 0;
   2916 	}
   2917 
   2918 	if (os_strcmp(var, "min_ul_bandwidth_home") == 0) {
   2919 		cred->min_ul_bandwidth_home = atoi(value);
   2920 		return 0;
   2921 	}
   2922 
   2923 	if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) {
   2924 		cred->min_dl_bandwidth_roaming = atoi(value);
   2925 		return 0;
   2926 	}
   2927 
   2928 	if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) {
   2929 		cred->min_ul_bandwidth_roaming = atoi(value);
   2930 		return 0;
   2931 	}
   2932 
   2933 	if (os_strcmp(var, "max_bss_load") == 0) {
   2934 		cred->max_bss_load = atoi(value);
   2935 		return 0;
   2936 	}
   2937 
   2938 	if (os_strcmp(var, "req_conn_capab") == 0)
   2939 		return wpa_config_set_cred_req_conn_capab(cred, value);
   2940 
   2941 	if (os_strcmp(var, "ocsp") == 0) {
   2942 		cred->ocsp = atoi(value);
   2943 		return 0;
   2944 	}
   2945 
   2946 	if (os_strcmp(var, "sim_num") == 0) {
   2947 		cred->sim_num = atoi(value);
   2948 		return 0;
   2949 	}
   2950 
   2951 	val = wpa_config_parse_string(value, &len);
   2952 	if (val == NULL ||
   2953 	    (os_strcmp(var, "excluded_ssid") != 0 &&
   2954 	     os_strcmp(var, "roaming_consortium") != 0 &&
   2955 	     os_strcmp(var, "required_roaming_consortium") != 0 &&
   2956 	     has_newline(val))) {
   2957 		wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
   2958 			   "value '%s'.", line, var, value);
   2959 		os_free(val);
   2960 		return -1;
   2961 	}
   2962 
   2963 	if (os_strcmp(var, "realm") == 0) {
   2964 		os_free(cred->realm);
   2965 		cred->realm = val;
   2966 		return 0;
   2967 	}
   2968 
   2969 	if (os_strcmp(var, "username") == 0) {
   2970 		str_clear_free(cred->username);
   2971 		cred->username = val;
   2972 		return 0;
   2973 	}
   2974 
   2975 	if (os_strcmp(var, "password") == 0) {
   2976 		str_clear_free(cred->password);
   2977 		cred->password = val;
   2978 		cred->ext_password = 0;
   2979 		return 0;
   2980 	}
   2981 
   2982 	if (os_strcmp(var, "ca_cert") == 0) {
   2983 		os_free(cred->ca_cert);
   2984 		cred->ca_cert = val;
   2985 		return 0;
   2986 	}
   2987 
   2988 	if (os_strcmp(var, "client_cert") == 0) {
   2989 		os_free(cred->client_cert);
   2990 		cred->client_cert = val;
   2991 		return 0;
   2992 	}
   2993 
   2994 	if (os_strcmp(var, "private_key") == 0) {
   2995 		os_free(cred->private_key);
   2996 		cred->private_key = val;
   2997 		return 0;
   2998 	}
   2999 
   3000 	if (os_strcmp(var, "private_key_passwd") == 0) {
   3001 		str_clear_free(cred->private_key_passwd);
   3002 		cred->private_key_passwd = val;
   3003 		return 0;
   3004 	}
   3005 
   3006 	if (os_strcmp(var, "imsi") == 0) {
   3007 		os_free(cred->imsi);
   3008 		cred->imsi = val;
   3009 		return 0;
   3010 	}
   3011 
   3012 	if (os_strcmp(var, "milenage") == 0) {
   3013 		str_clear_free(cred->milenage);
   3014 		cred->milenage = val;
   3015 		return 0;
   3016 	}
   3017 
   3018 	if (os_strcmp(var, "domain_suffix_match") == 0) {
   3019 		os_free(cred->domain_suffix_match);
   3020 		cred->domain_suffix_match = val;
   3021 		return 0;
   3022 	}
   3023 
   3024 	if (os_strcmp(var, "domain") == 0) {
   3025 		char **new_domain;
   3026 		new_domain = os_realloc_array(cred->domain,
   3027 					      cred->num_domain + 1,
   3028 					      sizeof(char *));
   3029 		if (new_domain == NULL) {
   3030 			os_free(val);
   3031 			return -1;
   3032 		}
   3033 		new_domain[cred->num_domain++] = val;
   3034 		cred->domain = new_domain;
   3035 		return 0;
   3036 	}
   3037 
   3038 	if (os_strcmp(var, "phase1") == 0) {
   3039 		os_free(cred->phase1);
   3040 		cred->phase1 = val;
   3041 		return 0;
   3042 	}
   3043 
   3044 	if (os_strcmp(var, "phase2") == 0) {
   3045 		os_free(cred->phase2);
   3046 		cred->phase2 = val;
   3047 		return 0;
   3048 	}
   3049 
   3050 	if (os_strcmp(var, "roaming_consortium") == 0) {
   3051 		if (len < 3 || len > sizeof(cred->roaming_consortium)) {
   3052 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   3053 				   "roaming_consortium length %d (3..15 "
   3054 				   "expected)", line, (int) len);
   3055 			os_free(val);
   3056 			return -1;
   3057 		}
   3058 		os_memcpy(cred->roaming_consortium, val, len);
   3059 		cred->roaming_consortium_len = len;
   3060 		os_free(val);
   3061 		return 0;
   3062 	}
   3063 
   3064 	if (os_strcmp(var, "required_roaming_consortium") == 0) {
   3065 		if (len < 3 || len > sizeof(cred->required_roaming_consortium))
   3066 		{
   3067 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   3068 				   "required_roaming_consortium length %d "
   3069 				   "(3..15 expected)", line, (int) len);
   3070 			os_free(val);
   3071 			return -1;
   3072 		}
   3073 		os_memcpy(cred->required_roaming_consortium, val, len);
   3074 		cred->required_roaming_consortium_len = len;
   3075 		os_free(val);
   3076 		return 0;
   3077 	}
   3078 
   3079 	if (os_strcmp(var, "excluded_ssid") == 0) {
   3080 		struct excluded_ssid *e;
   3081 
   3082 		if (len > SSID_MAX_LEN) {
   3083 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   3084 				   "excluded_ssid length %d", line, (int) len);
   3085 			os_free(val);
   3086 			return -1;
   3087 		}
   3088 
   3089 		e = os_realloc_array(cred->excluded_ssid,
   3090 				     cred->num_excluded_ssid + 1,
   3091 				     sizeof(struct excluded_ssid));
   3092 		if (e == NULL) {
   3093 			os_free(val);
   3094 			return -1;
   3095 		}
   3096 		cred->excluded_ssid = e;
   3097 
   3098 		e = &cred->excluded_ssid[cred->num_excluded_ssid++];
   3099 		os_memcpy(e->ssid, val, len);
   3100 		e->ssid_len = len;
   3101 
   3102 		os_free(val);
   3103 
   3104 		return 0;
   3105 	}
   3106 
   3107 	if (os_strcmp(var, "roaming_partner") == 0) {
   3108 		struct roaming_partner *p;
   3109 		char *pos;
   3110 
   3111 		p = os_realloc_array(cred->roaming_partner,
   3112 				     cred->num_roaming_partner + 1,
   3113 				     sizeof(struct roaming_partner));
   3114 		if (p == NULL) {
   3115 			os_free(val);
   3116 			return -1;
   3117 		}
   3118 		cred->roaming_partner = p;
   3119 
   3120 		p = &cred->roaming_partner[cred->num_roaming_partner];
   3121 
   3122 		pos = os_strchr(val, ',');
   3123 		if (pos == NULL) {
   3124 			os_free(val);
   3125 			return -1;
   3126 		}
   3127 		*pos++ = '\0';
   3128 		if (pos - val - 1 >= (int) sizeof(p->fqdn)) {
   3129 			os_free(val);
   3130 			return -1;
   3131 		}
   3132 		os_memcpy(p->fqdn, val, pos - val);
   3133 
   3134 		p->exact_match = atoi(pos);
   3135 
   3136 		pos = os_strchr(pos, ',');
   3137 		if (pos == NULL) {
   3138 			os_free(val);
   3139 			return -1;
   3140 		}
   3141 		*pos++ = '\0';
   3142 
   3143 		p->priority = atoi(pos);
   3144 
   3145 		pos = os_strchr(pos, ',');
   3146 		if (pos == NULL) {
   3147 			os_free(val);
   3148 			return -1;
   3149 		}
   3150 		*pos++ = '\0';
   3151 
   3152 		if (os_strlen(pos) >= sizeof(p->country)) {
   3153 			os_free(val);
   3154 			return -1;
   3155 		}
   3156 		os_memcpy(p->country, pos, os_strlen(pos) + 1);
   3157 
   3158 		cred->num_roaming_partner++;
   3159 		os_free(val);
   3160 
   3161 		return 0;
   3162 	}
   3163 
   3164 	if (os_strcmp(var, "provisioning_sp") == 0) {
   3165 		os_free(cred->provisioning_sp);
   3166 		cred->provisioning_sp = val;
   3167 		return 0;
   3168 	}
   3169 
   3170 	if (line) {
   3171 		wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
   3172 			   line, var);
   3173 	}
   3174 
   3175 	os_free(val);
   3176 
   3177 	return -1;
   3178 }
   3179 
   3180 
   3181 static char * alloc_int_str(int val)
   3182 {
   3183 	const unsigned int bufsize = 20;
   3184 	char *buf;
   3185 	int res;
   3186 
   3187 	buf = os_malloc(bufsize);
   3188 	if (buf == NULL)
   3189 		return NULL;
   3190 	res = os_snprintf(buf, bufsize, "%d", val);
   3191 	if (os_snprintf_error(bufsize, res)) {
   3192 		os_free(buf);
   3193 		buf = NULL;
   3194 	}
   3195 	return buf;
   3196 }
   3197 
   3198 
   3199 static char * alloc_strdup(const char *str)
   3200 {
   3201 	if (str == NULL)
   3202 		return NULL;
   3203 	return os_strdup(str);
   3204 }
   3205 
   3206 
   3207 char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
   3208 {
   3209 	if (os_strcmp(var, "temporary") == 0)
   3210 		return alloc_int_str(cred->temporary);
   3211 
   3212 	if (os_strcmp(var, "priority") == 0)
   3213 		return alloc_int_str(cred->priority);
   3214 
   3215 	if (os_strcmp(var, "sp_priority") == 0)
   3216 		return alloc_int_str(cred->sp_priority);
   3217 
   3218 	if (os_strcmp(var, "pcsc") == 0)
   3219 		return alloc_int_str(cred->pcsc);
   3220 
   3221 	if (os_strcmp(var, "eap") == 0) {
   3222 		if (!cred->eap_method)
   3223 			return NULL;
   3224 		return alloc_strdup(eap_get_name(cred->eap_method[0].vendor,
   3225 						 cred->eap_method[0].method));
   3226 	}
   3227 
   3228 	if (os_strcmp(var, "update_identifier") == 0)
   3229 		return alloc_int_str(cred->update_identifier);
   3230 
   3231 	if (os_strcmp(var, "min_dl_bandwidth_home") == 0)
   3232 		return alloc_int_str(cred->min_dl_bandwidth_home);
   3233 
   3234 	if (os_strcmp(var, "min_ul_bandwidth_home") == 0)
   3235 		return alloc_int_str(cred->min_ul_bandwidth_home);
   3236 
   3237 	if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0)
   3238 		return alloc_int_str(cred->min_dl_bandwidth_roaming);
   3239 
   3240 	if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0)
   3241 		return alloc_int_str(cred->min_ul_bandwidth_roaming);
   3242 
   3243 	if (os_strcmp(var, "max_bss_load") == 0)
   3244 		return alloc_int_str(cred->max_bss_load);
   3245 
   3246 	if (os_strcmp(var, "req_conn_capab") == 0) {
   3247 		unsigned int i;
   3248 		char *buf, *end, *pos;
   3249 		int ret;
   3250 
   3251 		if (!cred->num_req_conn_capab)
   3252 			return NULL;
   3253 
   3254 		buf = os_malloc(4000);
   3255 		if (buf == NULL)
   3256 			return NULL;
   3257 		pos = buf;
   3258 		end = pos + 4000;
   3259 		for (i = 0; i < cred->num_req_conn_capab; i++) {
   3260 			int *ports;
   3261 
   3262 			ret = os_snprintf(pos, end - pos, "%s%u",
   3263 					  i > 0 ? "\n" : "",
   3264 					  cred->req_conn_capab_proto[i]);
   3265 			if (os_snprintf_error(end - pos, ret))
   3266 				return buf;
   3267 			pos += ret;
   3268 
   3269 			ports = cred->req_conn_capab_port[i];
   3270 			if (ports) {
   3271 				int j;
   3272 				for (j = 0; ports[j] != -1; j++) {
   3273 					ret = os_snprintf(pos, end - pos,
   3274 							  "%s%d",
   3275 							  j > 0 ? "," : ":",
   3276 							  ports[j]);
   3277 					if (os_snprintf_error(end - pos, ret))
   3278 						return buf;
   3279 					pos += ret;
   3280 				}
   3281 			}
   3282 		}
   3283 
   3284 		return buf;
   3285 	}
   3286 
   3287 	if (os_strcmp(var, "ocsp") == 0)
   3288 		return alloc_int_str(cred->ocsp);
   3289 
   3290 	if (os_strcmp(var, "realm") == 0)
   3291 		return alloc_strdup(cred->realm);
   3292 
   3293 	if (os_strcmp(var, "username") == 0)
   3294 		return alloc_strdup(cred->username);
   3295 
   3296 	if (os_strcmp(var, "password") == 0) {
   3297 		if (!cred->password)
   3298 			return NULL;
   3299 		return alloc_strdup("*");
   3300 	}
   3301 
   3302 	if (os_strcmp(var, "ca_cert") == 0)
   3303 		return alloc_strdup(cred->ca_cert);
   3304 
   3305 	if (os_strcmp(var, "client_cert") == 0)
   3306 		return alloc_strdup(cred->client_cert);
   3307 
   3308 	if (os_strcmp(var, "private_key") == 0)
   3309 		return alloc_strdup(cred->private_key);
   3310 
   3311 	if (os_strcmp(var, "private_key_passwd") == 0) {
   3312 		if (!cred->private_key_passwd)
   3313 			return NULL;
   3314 		return alloc_strdup("*");
   3315 	}
   3316 
   3317 	if (os_strcmp(var, "imsi") == 0)
   3318 		return alloc_strdup(cred->imsi);
   3319 
   3320 	if (os_strcmp(var, "milenage") == 0) {
   3321 		if (!(cred->milenage))
   3322 			return NULL;
   3323 		return alloc_strdup("*");
   3324 	}
   3325 
   3326 	if (os_strcmp(var, "domain_suffix_match") == 0)
   3327 		return alloc_strdup(cred->domain_suffix_match);
   3328 
   3329 	if (os_strcmp(var, "domain") == 0) {
   3330 		unsigned int i;
   3331 		char *buf, *end, *pos;
   3332 		int ret;
   3333 
   3334 		if (!cred->num_domain)
   3335 			return NULL;
   3336 
   3337 		buf = os_malloc(4000);
   3338 		if (buf == NULL)
   3339 			return NULL;
   3340 		pos = buf;
   3341 		end = pos + 4000;
   3342 
   3343 		for (i = 0; i < cred->num_domain; i++) {
   3344 			ret = os_snprintf(pos, end - pos, "%s%s",
   3345 					  i > 0 ? "\n" : "", cred->domain[i]);
   3346 			if (os_snprintf_error(end - pos, ret))
   3347 				return buf;
   3348 			pos += ret;
   3349 		}
   3350 
   3351 		return buf;
   3352 	}
   3353 
   3354 	if (os_strcmp(var, "phase1") == 0)
   3355 		return alloc_strdup(cred->phase1);
   3356 
   3357 	if (os_strcmp(var, "phase2") == 0)
   3358 		return alloc_strdup(cred->phase2);
   3359 
   3360 	if (os_strcmp(var, "roaming_consortium") == 0) {
   3361 		size_t buflen;
   3362 		char *buf;
   3363 
   3364 		if (!cred->roaming_consortium_len)
   3365 			return NULL;
   3366 		buflen = cred->roaming_consortium_len * 2 + 1;
   3367 		buf = os_malloc(buflen);
   3368 		if (buf == NULL)
   3369 			return NULL;
   3370 		wpa_snprintf_hex(buf, buflen, cred->roaming_consortium,
   3371 				 cred->roaming_consortium_len);
   3372 		return buf;
   3373 	}
   3374 
   3375 	if (os_strcmp(var, "required_roaming_consortium") == 0) {
   3376 		size_t buflen;
   3377 		char *buf;
   3378 
   3379 		if (!cred->required_roaming_consortium_len)
   3380 			return NULL;
   3381 		buflen = cred->required_roaming_consortium_len * 2 + 1;
   3382 		buf = os_malloc(buflen);
   3383 		if (buf == NULL)
   3384 			return NULL;
   3385 		wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium,
   3386 				 cred->required_roaming_consortium_len);
   3387 		return buf;
   3388 	}
   3389 
   3390 	if (os_strcmp(var, "excluded_ssid") == 0) {
   3391 		unsigned int i;
   3392 		char *buf, *end, *pos;
   3393 
   3394 		if (!cred->num_excluded_ssid)
   3395 			return NULL;
   3396 
   3397 		buf = os_malloc(4000);
   3398 		if (buf == NULL)
   3399 			return NULL;
   3400 		pos = buf;
   3401 		end = pos + 4000;
   3402 
   3403 		for (i = 0; i < cred->num_excluded_ssid; i++) {
   3404 			struct excluded_ssid *e;
   3405 			int ret;
   3406 
   3407 			e = &cred->excluded_ssid[i];
   3408 			ret = os_snprintf(pos, end - pos, "%s%s",
   3409 					  i > 0 ? "\n" : "",
   3410 					  wpa_ssid_txt(e->ssid, e->ssid_len));
   3411 			if (os_snprintf_error(end - pos, ret))
   3412 				return buf;
   3413 			pos += ret;
   3414 		}
   3415 
   3416 		return buf;
   3417 	}
   3418 
   3419 	if (os_strcmp(var, "roaming_partner") == 0) {
   3420 		unsigned int i;
   3421 		char *buf, *end, *pos;
   3422 
   3423 		if (!cred->num_roaming_partner)
   3424 			return NULL;
   3425 
   3426 		buf = os_malloc(4000);
   3427 		if (buf == NULL)
   3428 			return NULL;
   3429 		pos = buf;
   3430 		end = pos + 4000;
   3431 
   3432 		for (i = 0; i < cred->num_roaming_partner; i++) {
   3433 			struct roaming_partner *p;
   3434 			int ret;
   3435 
   3436 			p = &cred->roaming_partner[i];
   3437 			ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s",
   3438 					  i > 0 ? "\n" : "",
   3439 					  p->fqdn, p->exact_match, p->priority,
   3440 					  p->country);
   3441 			if (os_snprintf_error(end - pos, ret))
   3442 				return buf;
   3443 			pos += ret;
   3444 		}
   3445 
   3446 		return buf;
   3447 	}
   3448 
   3449 	if (os_strcmp(var, "provisioning_sp") == 0)
   3450 		return alloc_strdup(cred->provisioning_sp);
   3451 
   3452 	return NULL;
   3453 }
   3454 
   3455 
   3456 struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
   3457 {
   3458 	struct wpa_cred *cred;
   3459 
   3460 	cred = config->cred;
   3461 	while (cred) {
   3462 		if (id == cred->id)
   3463 			break;
   3464 		cred = cred->next;
   3465 	}
   3466 
   3467 	return cred;
   3468 }
   3469 
   3470 
   3471 struct wpa_cred * wpa_config_add_cred(struct wpa_config *config)
   3472 {
   3473 	int id;
   3474 	struct wpa_cred *cred, *last = NULL;
   3475 
   3476 	id = -1;
   3477 	cred = config->cred;
   3478 	while (cred) {
   3479 		if (cred->id > id)
   3480 			id = cred->id;
   3481 		last = cred;
   3482 		cred = cred->next;
   3483 	}
   3484 	id++;
   3485 
   3486 	cred = os_zalloc(sizeof(*cred));
   3487 	if (cred == NULL)
   3488 		return NULL;
   3489 	cred->id = id;
   3490 	cred->sim_num = DEFAULT_USER_SELECTED_SIM;
   3491 	if (last)
   3492 		last->next = cred;
   3493 	else
   3494 		config->cred = cred;
   3495 
   3496 	return cred;
   3497 }
   3498 
   3499 
   3500 int wpa_config_remove_cred(struct wpa_config *config, int id)
   3501 {
   3502 	struct wpa_cred *cred, *prev = NULL;
   3503 
   3504 	cred = config->cred;
   3505 	while (cred) {
   3506 		if (id == cred->id)
   3507 			break;
   3508 		prev = cred;
   3509 		cred = cred->next;
   3510 	}
   3511 
   3512 	if (cred == NULL)
   3513 		return -1;
   3514 
   3515 	if (prev)
   3516 		prev->next = cred->next;
   3517 	else
   3518 		config->cred = cred->next;
   3519 
   3520 	wpa_config_free_cred(cred);
   3521 	return 0;
   3522 }
   3523 
   3524 
   3525 #ifndef CONFIG_NO_CONFIG_BLOBS
   3526 /**
   3527  * wpa_config_get_blob - Get a named configuration blob
   3528  * @config: Configuration data from wpa_config_read()
   3529  * @name: Name of the blob
   3530  * Returns: Pointer to blob data or %NULL if not found
   3531  */
   3532 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
   3533 						   const char *name)
   3534 {
   3535 	struct wpa_config_blob *blob = config->blobs;
   3536 
   3537 	while (blob) {
   3538 		if (os_strcmp(blob->name, name) == 0)
   3539 			return blob;
   3540 		blob = blob->next;
   3541 	}
   3542 	return NULL;
   3543 }
   3544 
   3545 
   3546 /**
   3547  * wpa_config_set_blob - Set or add a named configuration blob
   3548  * @config: Configuration data from wpa_config_read()
   3549  * @blob: New value for the blob
   3550  *
   3551  * Adds a new configuration blob or replaces the current value of an existing
   3552  * blob.
   3553  */
   3554 void wpa_config_set_blob(struct wpa_config *config,
   3555 			 struct wpa_config_blob *blob)
   3556 {
   3557 	wpa_config_remove_blob(config, blob->name);
   3558 	blob->next = config->blobs;
   3559 	config->blobs = blob;
   3560 }
   3561 
   3562 
   3563 /**
   3564  * wpa_config_free_blob - Free blob data
   3565  * @blob: Pointer to blob to be freed
   3566  */
   3567 void wpa_config_free_blob(struct wpa_config_blob *blob)
   3568 {
   3569 	if (blob) {
   3570 		os_free(blob->name);
   3571 		bin_clear_free(blob->data, blob->len);
   3572 		os_free(blob);
   3573 	}
   3574 }
   3575 
   3576 
   3577 /**
   3578  * wpa_config_remove_blob - Remove a named configuration blob
   3579  * @config: Configuration data from wpa_config_read()
   3580  * @name: Name of the blob to remove
   3581  * Returns: 0 if blob was removed or -1 if blob was not found
   3582  */
   3583 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
   3584 {
   3585 	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
   3586 
   3587 	while (pos) {
   3588 		if (os_strcmp(pos->name, name) == 0) {
   3589 			if (prev)
   3590 				prev->next = pos->next;
   3591 			else
   3592 				config->blobs = pos->next;
   3593 			wpa_config_free_blob(pos);
   3594 			return 0;
   3595 		}
   3596 		prev = pos;
   3597 		pos = pos->next;
   3598 	}
   3599 
   3600 	return -1;
   3601 }
   3602 #endif /* CONFIG_NO_CONFIG_BLOBS */
   3603 
   3604 
   3605 /**
   3606  * wpa_config_alloc_empty - Allocate an empty configuration
   3607  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
   3608  * socket
   3609  * @driver_param: Driver parameters
   3610  * Returns: Pointer to allocated configuration data or %NULL on failure
   3611  */
   3612 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
   3613 					   const char *driver_param)
   3614 {
   3615 	struct wpa_config *config;
   3616 	const int aCWmin = 4, aCWmax = 10;
   3617 	const struct hostapd_wmm_ac_params ac_bk =
   3618 		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
   3619 	const struct hostapd_wmm_ac_params ac_be =
   3620 		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
   3621 	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
   3622 		{ aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
   3623 	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
   3624 		{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
   3625 
   3626 	config = os_zalloc(sizeof(*config));
   3627 	if (config == NULL)
   3628 		return NULL;
   3629 	config->eapol_version = DEFAULT_EAPOL_VERSION;
   3630 	config->ap_scan = DEFAULT_AP_SCAN;
   3631 	config->user_mpm = DEFAULT_USER_MPM;
   3632 	config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
   3633 	config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
   3634 	config->dot11RSNASAERetransPeriod =
   3635 		DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
   3636 	config->fast_reauth = DEFAULT_FAST_REAUTH;
   3637 	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
   3638 	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
   3639 	config->p2p_go_freq_change_policy = DEFAULT_P2P_GO_FREQ_MOVE;
   3640 	config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
   3641 	config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN;
   3642 	config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW;
   3643 	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
   3644 	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
   3645 	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
   3646 	config->max_num_sta = DEFAULT_MAX_NUM_STA;
   3647 	config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
   3648 	config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
   3649 	config->wmm_ac_params[0] = ac_be;
   3650 	config->wmm_ac_params[1] = ac_bk;
   3651 	config->wmm_ac_params[2] = ac_vi;
   3652 	config->wmm_ac_params[3] = ac_vo;
   3653 	config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
   3654 	config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
   3655 	config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
   3656 	config->cert_in_cb = DEFAULT_CERT_IN_CB;
   3657 	config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION;
   3658 
   3659 #ifdef CONFIG_MBO
   3660 	config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
   3661 #endif /* CONFIG_MBO */
   3662 
   3663 	if (ctrl_interface)
   3664 		config->ctrl_interface = os_strdup(ctrl_interface);
   3665 	if (driver_param)
   3666 		config->driver_param = os_strdup(driver_param);
   3667 
   3668 	return config;
   3669 }
   3670 
   3671 
   3672 #ifndef CONFIG_NO_STDOUT_DEBUG
   3673 /**
   3674  * wpa_config_debug_dump_networks - Debug dump of configured networks
   3675  * @config: Configuration data from wpa_config_read()
   3676  */
   3677 void wpa_config_debug_dump_networks(struct wpa_config *config)
   3678 {
   3679 	int prio;
   3680 	struct wpa_ssid *ssid;
   3681 
   3682 	for (prio = 0; prio < config->num_prio; prio++) {
   3683 		ssid = config->pssid[prio];
   3684 		wpa_printf(MSG_DEBUG, "Priority group %d",
   3685 			   ssid->priority);
   3686 		while (ssid) {
   3687 			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
   3688 				   ssid->id,
   3689 				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
   3690 			ssid = ssid->pnext;
   3691 		}
   3692 	}
   3693 }
   3694 #endif /* CONFIG_NO_STDOUT_DEBUG */
   3695 
   3696 
   3697 struct global_parse_data {
   3698 	char *name;
   3699 	int (*parser)(const struct global_parse_data *data,
   3700 		      struct wpa_config *config, int line, const char *value);
   3701 	int (*get)(const char *name, struct wpa_config *config, long offset,
   3702 		   char *buf, size_t buflen, int pretty_print);
   3703 	void *param1, *param2, *param3;
   3704 	unsigned int changed_flag;
   3705 };
   3706 
   3707 
   3708 static int wpa_global_config_parse_int(const struct global_parse_data *data,
   3709 				       struct wpa_config *config, int line,
   3710 				       const char *pos)
   3711 {
   3712 	int val, *dst;
   3713 	char *end;
   3714 
   3715 	dst = (int *) (((u8 *) config) + (long) data->param1);
   3716 	val = strtol(pos, &end, 0);
   3717 	if (*end) {
   3718 		wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
   3719 			   line, pos);
   3720 		return -1;
   3721 	}
   3722 	*dst = val;
   3723 
   3724 	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
   3725 
   3726 	if (data->param2 && *dst < (long) data->param2) {
   3727 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
   3728 			   "min_value=%ld)", line, data->name, *dst,
   3729 			   (long) data->param2);
   3730 		*dst = (long) data->param2;
   3731 		return -1;
   3732 	}
   3733 
   3734 	if (data->param3 && *dst > (long) data->param3) {
   3735 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
   3736 			   "max_value=%ld)", line, data->name, *dst,
   3737 			   (long) data->param3);
   3738 		*dst = (long) data->param3;
   3739 		return -1;
   3740 	}
   3741 
   3742 	return 0;
   3743 }
   3744 
   3745 
   3746 static int wpa_global_config_parse_str(const struct global_parse_data *data,
   3747 				       struct wpa_config *config, int line,
   3748 				       const char *pos)
   3749 {
   3750 	size_t len;
   3751 	char **dst, *tmp;
   3752 
   3753 	len = os_strlen(pos);
   3754 	if (data->param2 && len < (size_t) data->param2) {
   3755 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
   3756 			   "min_len=%ld)", line, data->name,
   3757 			   (unsigned long) len, (long) data->param2);
   3758 		return -1;
   3759 	}
   3760 
   3761 	if (data->param3 && len > (size_t) data->param3) {
   3762 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
   3763 			   "max_len=%ld)", line, data->name,
   3764 			   (unsigned long) len, (long) data->param3);
   3765 		return -1;
   3766 	}
   3767 
   3768 	if (has_newline(pos)) {
   3769 		wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
   3770 			   line, data->name);
   3771 		return -1;
   3772 	}
   3773 
   3774 	tmp = os_strdup(pos);
   3775 	if (tmp == NULL)
   3776 		return -1;
   3777 
   3778 	dst = (char **) (((u8 *) config) + (long) data->param1);
   3779 	os_free(*dst);
   3780 	*dst = tmp;
   3781 	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
   3782 
   3783 	return 0;
   3784 }
   3785 
   3786 
   3787 static int wpa_config_process_bgscan(const struct global_parse_data *data,
   3788 				     struct wpa_config *config, int line,
   3789 				     const char *pos)
   3790 {
   3791 	size_t len;
   3792 	char *tmp;
   3793 	int res;
   3794 
   3795 	tmp = wpa_config_parse_string(pos, &len);
   3796 	if (tmp == NULL) {
   3797 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s",
   3798 			   line, data->name);
   3799 		return -1;
   3800 	}
   3801 
   3802 	res = wpa_global_config_parse_str(data, config, line, tmp);
   3803 	os_free(tmp);
   3804 	return res;
   3805 }
   3806 
   3807 
   3808 static int wpa_global_config_parse_bin(const struct global_parse_data *data,
   3809 				       struct wpa_config *config, int line,
   3810 				       const char *pos)
   3811 {
   3812 	struct wpabuf **dst, *tmp;
   3813 
   3814 	tmp = wpabuf_parse_bin(pos);
   3815 	if (!tmp)
   3816 		return -1;
   3817 
   3818 	dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
   3819 	wpabuf_free(*dst);
   3820 	*dst = tmp;
   3821 	wpa_printf(MSG_DEBUG, "%s", data->name);
   3822 
   3823 	return 0;
   3824 }
   3825 
   3826 
   3827 static int wpa_config_process_freq_list(const struct global_parse_data *data,
   3828 					struct wpa_config *config, int line,
   3829 					const char *value)
   3830 {
   3831 	int *freqs;
   3832 
   3833 	freqs = wpa_config_parse_int_array(value);
   3834 	if (freqs == NULL)
   3835 		return -1;
   3836 	if (freqs[0] == 0) {
   3837 		os_free(freqs);
   3838 		freqs = NULL;
   3839 	}
   3840 	os_free(config->freq_list);
   3841 	config->freq_list = freqs;
   3842 	return 0;
   3843 }
   3844 
   3845 
   3846 #ifdef CONFIG_P2P
   3847 static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
   3848 					struct wpa_config *config, int line,
   3849 					const char *pos)
   3850 {
   3851 	u32 *dst;
   3852 	struct hostapd_ip_addr addr;
   3853 
   3854 	if (hostapd_parse_ip_addr(pos, &addr) < 0)
   3855 		return -1;
   3856 	if (addr.af != AF_INET)
   3857 		return -1;
   3858 
   3859 	dst = (u32 *) (((u8 *) config) + (long) data->param1);
   3860 	os_memcpy(dst, &addr.u.v4.s_addr, 4);
   3861 	wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name,
   3862 		   WPA_GET_BE32((u8 *) dst));
   3863 
   3864 	return 0;
   3865 }
   3866 #endif /* CONFIG_P2P */
   3867 
   3868 
   3869 static int wpa_config_process_country(const struct global_parse_data *data,
   3870 				      struct wpa_config *config, int line,
   3871 				      const char *pos)
   3872 {
   3873 	if (!pos[0] || !pos[1]) {
   3874 		wpa_printf(MSG_DEBUG, "Invalid country set");
   3875 		return -1;
   3876 	}
   3877 	config->country[0] = pos[0];
   3878 	config->country[1] = pos[1];
   3879 	wpa_printf(MSG_DEBUG, "country='%c%c'",
   3880 		   config->country[0], config->country[1]);
   3881 	return 0;
   3882 }
   3883 
   3884 
   3885 static int wpa_config_process_load_dynamic_eap(
   3886 	const struct global_parse_data *data, struct wpa_config *config,
   3887 	int line, const char *so)
   3888 {
   3889 	int ret;
   3890 	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
   3891 	ret = eap_peer_method_load(so);
   3892 	if (ret == -2) {
   3893 		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
   3894 			   "reloading.");
   3895 	} else if (ret) {
   3896 		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
   3897 			   "method '%s'.", line, so);
   3898 		return -1;
   3899 	}
   3900 
   3901 	return 0;
   3902 }
   3903 
   3904 
   3905 #ifdef CONFIG_WPS
   3906 
   3907 static int wpa_config_process_uuid(const struct global_parse_data *data,
   3908 				   struct wpa_config *config, int line,
   3909 				   const char *pos)
   3910 {
   3911 	char buf[40];
   3912 	if (uuid_str2bin(pos, config->uuid)) {
   3913 		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
   3914 		return -1;
   3915 	}
   3916 	uuid_bin2str(config->uuid, buf, sizeof(buf));
   3917 	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
   3918 	return 0;
   3919 }
   3920 
   3921 
   3922 static int wpa_config_process_device_type(
   3923 	const struct global_parse_data *data,
   3924 	struct wpa_config *config, int line, const char *pos)
   3925 {
   3926 	return wps_dev_type_str2bin(pos, config->device_type);
   3927 }
   3928 
   3929 
   3930 static int wpa_config_process_os_version(const struct global_parse_data *data,
   3931 					 struct wpa_config *config, int line,
   3932 					 const char *pos)
   3933 {
   3934 	if (hexstr2bin(pos, config->os_version, 4)) {
   3935 		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
   3936 		return -1;
   3937 	}
   3938 	wpa_printf(MSG_DEBUG, "os_version=%08x",
   3939 		   WPA_GET_BE32(config->os_version));
   3940 	return 0;
   3941 }
   3942 
   3943 
   3944 static int wpa_config_process_wps_vendor_ext_m1(
   3945 	const struct global_parse_data *data,
   3946 	struct wpa_config *config, int line, const char *pos)
   3947 {
   3948 	struct wpabuf *tmp;
   3949 	int len = os_strlen(pos) / 2;
   3950 	u8 *p;
   3951 
   3952 	if (!len) {
   3953 		wpa_printf(MSG_ERROR, "Line %d: "
   3954 			   "invalid wps_vendor_ext_m1", line);
   3955 		return -1;
   3956 	}
   3957 
   3958 	tmp = wpabuf_alloc(len);
   3959 	if (tmp) {
   3960 		p = wpabuf_put(tmp, len);
   3961 
   3962 		if (hexstr2bin(pos, p, len)) {
   3963 			wpa_printf(MSG_ERROR, "Line %d: "
   3964 				   "invalid wps_vendor_ext_m1", line);
   3965 			wpabuf_free(tmp);
   3966 			return -1;
   3967 		}
   3968 
   3969 		wpabuf_free(config->wps_vendor_ext_m1);
   3970 		config->wps_vendor_ext_m1 = tmp;
   3971 	} else {
   3972 		wpa_printf(MSG_ERROR, "Can not allocate "
   3973 			   "memory for wps_vendor_ext_m1");
   3974 		return -1;
   3975 	}
   3976 
   3977 	return 0;
   3978 }
   3979 
   3980 #endif /* CONFIG_WPS */
   3981 
   3982 #ifdef CONFIG_P2P
   3983 static int wpa_config_process_sec_device_type(
   3984 	const struct global_parse_data *data,
   3985 	struct wpa_config *config, int line, const char *pos)
   3986 {
   3987 	int idx;
   3988 
   3989 	if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
   3990 		wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
   3991 			   "items", line);
   3992 		return -1;
   3993 	}
   3994 
   3995 	idx = config->num_sec_device_types;
   3996 
   3997 	if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
   3998 		return -1;
   3999 
   4000 	config->num_sec_device_types++;
   4001 	return 0;
   4002 }
   4003 
   4004 
   4005 static int wpa_config_process_p2p_pref_chan(
   4006 	const struct global_parse_data *data,
   4007 	struct wpa_config *config, int line, const char *pos)
   4008 {
   4009 	struct p2p_channel *pref = NULL, *n;
   4010 	unsigned int num = 0;
   4011 	const char *pos2;
   4012 	u8 op_class, chan;
   4013 
   4014 	/* format: class:chan,class:chan,... */
   4015 
   4016 	while (*pos) {
   4017 		op_class = atoi(pos);
   4018 		pos2 = os_strchr(pos, ':');
   4019 		if (pos2 == NULL)
   4020 			goto fail;
   4021 		pos2++;
   4022 		chan = atoi(pos2);
   4023 
   4024 		n = os_realloc_array(pref, num + 1,
   4025 				     sizeof(struct p2p_channel));
   4026 		if (n == NULL)
   4027 			goto fail;
   4028 		pref = n;
   4029 		pref[num].op_class = op_class;
   4030 		pref[num].chan = chan;
   4031 		num++;
   4032 
   4033 		pos = os_strchr(pos2, ',');
   4034 		if (pos == NULL)
   4035 			break;
   4036 		pos++;
   4037 	}
   4038 
   4039 	os_free(config->p2p_pref_chan);
   4040 	config->p2p_pref_chan = pref;
   4041 	config->num_p2p_pref_chan = num;
   4042 	wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs",
   4043 		    (u8 *) config->p2p_pref_chan,
   4044 		    config->num_p2p_pref_chan * sizeof(struct p2p_channel));
   4045 
   4046 	return 0;
   4047 
   4048 fail:
   4049 	os_free(pref);
   4050 	wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line);
   4051 	return -1;
   4052 }
   4053 
   4054 
   4055 static int wpa_config_process_p2p_no_go_freq(
   4056 	const struct global_parse_data *data,
   4057 	struct wpa_config *config, int line, const char *pos)
   4058 {
   4059 	int ret;
   4060 
   4061 	ret = freq_range_list_parse(&config->p2p_no_go_freq, pos);
   4062 	if (ret < 0) {
   4063 		wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_no_go_freq", line);
   4064 		return -1;
   4065 	}
   4066 
   4067 	wpa_printf(MSG_DEBUG, "P2P: p2p_no_go_freq with %u items",
   4068 		   config->p2p_no_go_freq.num);
   4069 
   4070 	return 0;
   4071 }
   4072 
   4073 #endif /* CONFIG_P2P */
   4074 
   4075 
   4076 static int wpa_config_process_hessid(
   4077 	const struct global_parse_data *data,
   4078 	struct wpa_config *config, int line, const char *pos)
   4079 {
   4080 	if (hwaddr_aton2(pos, config->hessid) < 0) {
   4081 		wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
   4082 			   line, pos);
   4083 		return -1;
   4084 	}
   4085 
   4086 	return 0;
   4087 }
   4088 
   4089 
   4090 static int wpa_config_process_sae_groups(
   4091 	const struct global_parse_data *data,
   4092 	struct wpa_config *config, int line, const char *pos)
   4093 {
   4094 	int *groups = wpa_config_parse_int_array(pos);
   4095 	if (groups == NULL) {
   4096 		wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'",
   4097 			   line, pos);
   4098 		return -1;
   4099 	}
   4100 
   4101 	os_free(config->sae_groups);
   4102 	config->sae_groups = groups;
   4103 
   4104 	return 0;
   4105 }
   4106 
   4107 
   4108 static int wpa_config_process_ap_vendor_elements(
   4109 	const struct global_parse_data *data,
   4110 	struct wpa_config *config, int line, const char *pos)
   4111 {
   4112 	struct wpabuf *tmp;
   4113 	int len = os_strlen(pos) / 2;
   4114 	u8 *p;
   4115 
   4116 	if (!len) {
   4117 		wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
   4118 			   line);
   4119 		return -1;
   4120 	}
   4121 
   4122 	tmp = wpabuf_alloc(len);
   4123 	if (tmp) {
   4124 		p = wpabuf_put(tmp, len);
   4125 
   4126 		if (hexstr2bin(pos, p, len)) {
   4127 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   4128 				   "ap_vendor_elements", line);
   4129 			wpabuf_free(tmp);
   4130 			return -1;
   4131 		}
   4132 
   4133 		wpabuf_free(config->ap_vendor_elements);
   4134 		config->ap_vendor_elements = tmp;
   4135 	} else {
   4136 		wpa_printf(MSG_ERROR, "Cannot allocate memory for "
   4137 			   "ap_vendor_elements");
   4138 		return -1;
   4139 	}
   4140 
   4141 	return 0;
   4142 }
   4143 
   4144 
   4145 #ifdef CONFIG_CTRL_IFACE
   4146 static int wpa_config_process_no_ctrl_interface(
   4147 	const struct global_parse_data *data,
   4148 	struct wpa_config *config, int line, const char *pos)
   4149 {
   4150 	wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL");
   4151 	os_free(config->ctrl_interface);
   4152 	config->ctrl_interface = NULL;
   4153 	return 0;
   4154 }
   4155 #endif /* CONFIG_CTRL_IFACE */
   4156 
   4157 
   4158 static int wpa_config_get_int(const char *name, struct wpa_config *config,
   4159 			      long offset, char *buf, size_t buflen,
   4160 			      int pretty_print)
   4161 {
   4162 	int *val = (int *) (((u8 *) config) + (long) offset);
   4163 
   4164 	if (pretty_print)
   4165 		return os_snprintf(buf, buflen, "%s=%d\n", name, *val);
   4166 	return os_snprintf(buf, buflen, "%d", *val);
   4167 }
   4168 
   4169 
   4170 static int wpa_config_get_str(const char *name, struct wpa_config *config,
   4171 			      long offset, char *buf, size_t buflen,
   4172 			      int pretty_print)
   4173 {
   4174 	char **val = (char **) (((u8 *) config) + (long) offset);
   4175 	int res;
   4176 
   4177 	if (pretty_print)
   4178 		res = os_snprintf(buf, buflen, "%s=%s\n", name,
   4179 				  *val ? *val : "null");
   4180 	else if (!*val)
   4181 		return -1;
   4182 	else
   4183 		res = os_snprintf(buf, buflen, "%s", *val);
   4184 	if (os_snprintf_error(buflen, res))
   4185 		res = -1;
   4186 
   4187 	return res;
   4188 }
   4189 
   4190 
   4191 #ifdef CONFIG_P2P
   4192 static int wpa_config_get_ipv4(const char *name, struct wpa_config *config,
   4193 			       long offset, char *buf, size_t buflen,
   4194 			       int pretty_print)
   4195 {
   4196 	void *val = ((u8 *) config) + (long) offset;
   4197 	int res;
   4198 	char addr[INET_ADDRSTRLEN];
   4199 
   4200 	if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr)))
   4201 		return -1;
   4202 
   4203 	if (pretty_print)
   4204 		res = os_snprintf(buf, buflen, "%s=%s\n", name, addr);
   4205 	else
   4206 		res = os_snprintf(buf, buflen, "%s", addr);
   4207 
   4208 	if (os_snprintf_error(buflen, res))
   4209 		res = -1;
   4210 
   4211 	return res;
   4212 }
   4213 #endif /* CONFIG_P2P */
   4214 
   4215 
   4216 #ifdef OFFSET
   4217 #undef OFFSET
   4218 #endif /* OFFSET */
   4219 /* OFFSET: Get offset of a variable within the wpa_config structure */
   4220 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
   4221 
   4222 #define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL
   4223 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL
   4224 #define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f)
   4225 #define INT(f) _INT(f), NULL, NULL
   4226 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
   4227 #define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f)
   4228 #define STR(f) _STR(f), NULL, NULL
   4229 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
   4230 #define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL
   4231 #define IPV4(f) #f, wpa_global_config_parse_ipv4, wpa_config_get_ipv4,  \
   4232 	OFFSET(f), NULL, NULL
   4233 
   4234 static const struct global_parse_data global_fields[] = {
   4235 #ifdef CONFIG_CTRL_IFACE
   4236 	{ STR(ctrl_interface), 0 },
   4237 	{ FUNC_NO_VAR(no_ctrl_interface), 0 },
   4238 	{ STR(ctrl_interface_group), 0 } /* deprecated */,
   4239 #endif /* CONFIG_CTRL_IFACE */
   4240 #ifdef CONFIG_MACSEC
   4241 	{ INT_RANGE(eapol_version, 1, 3), 0 },
   4242 #else /* CONFIG_MACSEC */
   4243 	{ INT_RANGE(eapol_version, 1, 2), 0 },
   4244 #endif /* CONFIG_MACSEC */
   4245 	{ INT(ap_scan), 0 },
   4246 	{ FUNC(bgscan), 0 },
   4247 #ifdef CONFIG_MESH
   4248 	{ INT(user_mpm), 0 },
   4249 	{ INT_RANGE(max_peer_links, 0, 255), 0 },
   4250 	{ INT(mesh_max_inactivity), 0 },
   4251 	{ INT(dot11RSNASAERetransPeriod), 0 },
   4252 #endif /* CONFIG_MESH */
   4253 	{ INT(disable_scan_offload), 0 },
   4254 	{ INT(fast_reauth), 0 },
   4255 	{ STR(opensc_engine_path), 0 },
   4256 	{ STR(pkcs11_engine_path), 0 },
   4257 	{ STR(pkcs11_module_path), 0 },
   4258 	{ STR(openssl_ciphers), 0 },
   4259 	{ STR(pcsc_reader), 0 },
   4260 	{ STR(pcsc_pin), 0 },
   4261 	{ INT(external_sim), 0 },
   4262 	{ STR(driver_param), 0 },
   4263 	{ INT(dot11RSNAConfigPMKLifetime), 0 },
   4264 	{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
   4265 	{ INT(dot11RSNAConfigSATimeout), 0 },
   4266 #ifndef CONFIG_NO_CONFIG_WRITE
   4267 	{ INT(update_config), 0 },
   4268 #endif /* CONFIG_NO_CONFIG_WRITE */
   4269 	{ FUNC_NO_VAR(load_dynamic_eap), 0 },
   4270 #ifdef CONFIG_WPS
   4271 	{ FUNC(uuid), CFG_CHANGED_UUID },
   4272 	{ STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN),
   4273 	  CFG_CHANGED_DEVICE_NAME },
   4274 	{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
   4275 	{ STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
   4276 	{ STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
   4277 	{ STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
   4278 	{ FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
   4279 	{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
   4280 	{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
   4281 	{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
   4282 	{ FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
   4283 #endif /* CONFIG_WPS */
   4284 #ifdef CONFIG_P2P
   4285 	{ FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
   4286 	{ INT(p2p_listen_reg_class), CFG_CHANGED_P2P_LISTEN_CHANNEL },
   4287 	{ INT(p2p_listen_channel), CFG_CHANGED_P2P_LISTEN_CHANNEL },
   4288 	{ INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL },
   4289 	{ INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL },
   4290 	{ INT_RANGE(p2p_go_intent, 0, 15), 0 },
   4291 	{ STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
   4292 	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
   4293 	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
   4294 	{ INT(p2p_group_idle), 0 },
   4295 	{ INT_RANGE(p2p_go_freq_change_policy, 0, P2P_GO_FREQ_MOVE_MAX), 0 },
   4296 	{ INT_RANGE(p2p_passphrase_len, 8, 63),
   4297 	  CFG_CHANGED_P2P_PASSPHRASE_LEN },
   4298 	{ FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
   4299 	{ FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN },
   4300 	{ INT_RANGE(p2p_add_cli_chan, 0, 1), 0 },
   4301 	{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
   4302 	{ INT(p2p_go_ht40), 0 },
   4303 	{ INT(p2p_go_vht), 0 },
   4304 	{ INT(p2p_disabled), 0 },
   4305 	{ INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
   4306 	{ INT(p2p_no_group_iface), 0 },
   4307 	{ INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
   4308 	{ IPV4(ip_addr_go), 0 },
   4309 	{ IPV4(ip_addr_mask), 0 },
   4310 	{ IPV4(ip_addr_start), 0 },
   4311 	{ IPV4(ip_addr_end), 0 },
   4312 	{ INT_RANGE(p2p_cli_probe, 0, 1), 0 },
   4313 #endif /* CONFIG_P2P */
   4314 	{ FUNC(country), CFG_CHANGED_COUNTRY },
   4315 	{ INT(bss_max_count), 0 },
   4316 	{ INT(bss_expiration_age), 0 },
   4317 	{ INT(bss_expiration_scan_count), 0 },
   4318 	{ INT_RANGE(filter_ssids, 0, 1), 0 },
   4319 	{ INT_RANGE(filter_rssi, -100, 0), 0 },
   4320 	{ INT(max_num_sta), 0 },
   4321 	{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
   4322 #ifdef CONFIG_HS20
   4323 	{ INT_RANGE(hs20, 0, 1), 0 },
   4324 #endif /* CONFIG_HS20 */
   4325 	{ INT_RANGE(interworking, 0, 1), 0 },
   4326 	{ FUNC(hessid), 0 },
   4327 	{ INT_RANGE(access_network_type, 0, 15), 0 },
   4328 	{ INT_RANGE(pbc_in_m1, 0, 1), 0 },
   4329 	{ STR(autoscan), 0 },
   4330 	{ INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
   4331 	  CFG_CHANGED_NFC_PASSWORD_TOKEN },
   4332 	{ BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
   4333 	{ BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
   4334 	{ BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN },
   4335 	{ STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
   4336 	{ INT(p2p_go_max_inactivity), 0 },
   4337 	{ INT_RANGE(auto_interworking, 0, 1), 0 },
   4338 	{ INT(okc), 0 },
   4339 	{ INT(pmf), 0 },
   4340 	{ FUNC(sae_groups), 0 },
   4341 	{ INT(dtim_period), 0 },
   4342 	{ INT(beacon_int), 0 },
   4343 	{ FUNC(ap_vendor_elements), 0 },
   4344 	{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
   4345 	{ FUNC(freq_list), 0 },
   4346 	{ INT(scan_cur_freq), 0 },
   4347 	{ INT(sched_scan_interval), 0 },
   4348 	{ INT(tdls_external_control), 0},
   4349 	{ STR(osu_dir), 0 },
   4350 	{ STR(wowlan_triggers), 0 },
   4351 	{ INT(p2p_search_delay), 0},
   4352 	{ INT(mac_addr), 0 },
   4353 	{ INT(rand_addr_lifetime), 0 },
   4354 	{ INT(preassoc_mac_addr), 0 },
   4355 	{ INT(key_mgmt_offload), 0},
   4356 	{ INT(passive_scan), 0 },
   4357 	{ INT(reassoc_same_bss_optim), 0 },
   4358 	{ INT(wps_priority), 0},
   4359 #ifdef CONFIG_FST
   4360 	{ STR_RANGE(fst_group_id, 1, FST_MAX_GROUP_ID_LEN), 0 },
   4361 	{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
   4362 	{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
   4363 #endif /* CONFIG_FST */
   4364 	{ INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
   4365 	{ STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS },
   4366 #ifdef CONFIG_MBO
   4367 	{ STR(non_pref_chan), 0 },
   4368 	{ INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE,
   4369 		    MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
   4370 #endif /*CONFIG_MBO */
   4371 	{ INT(gas_address3), 0 },
   4372 	{ INT_RANGE(ftm_responder, 0, 1), 0 },
   4373 	{ INT_RANGE(ftm_initiator, 0, 1), 0 },
   4374 };
   4375 
   4376 #undef FUNC
   4377 #undef _INT
   4378 #undef INT
   4379 #undef INT_RANGE
   4380 #undef _STR
   4381 #undef STR
   4382 #undef STR_RANGE
   4383 #undef BIN
   4384 #undef IPV4
   4385 #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields)
   4386 
   4387 
   4388 int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen)
   4389 {
   4390 	int result = 0;
   4391 	size_t i;
   4392 
   4393 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   4394 		const struct global_parse_data *field = &global_fields[i];
   4395 		int tmp;
   4396 
   4397 		if (!field->get)
   4398 			continue;
   4399 
   4400 		tmp = field->get(field->name, config, (long) field->param1,
   4401 				 buf, buflen, 1);
   4402 		if (tmp < 0)
   4403 			return -1;
   4404 		buf += tmp;
   4405 		buflen -= tmp;
   4406 		result += tmp;
   4407 	}
   4408 	return result;
   4409 }
   4410 
   4411 
   4412 int wpa_config_get_value(const char *name, struct wpa_config *config,
   4413 			 char *buf, size_t buflen)
   4414 {
   4415 	size_t i;
   4416 
   4417 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   4418 		const struct global_parse_data *field = &global_fields[i];
   4419 
   4420 		if (os_strcmp(name, field->name) != 0)
   4421 			continue;
   4422 		if (!field->get)
   4423 			break;
   4424 		return field->get(name, config, (long) field->param1,
   4425 				  buf, buflen, 0);
   4426 	}
   4427 
   4428 	return -1;
   4429 }
   4430 
   4431 
   4432 int wpa_config_get_num_global_field_names(void)
   4433 {
   4434 	return NUM_GLOBAL_FIELDS;
   4435 }
   4436 
   4437 
   4438 const char * wpa_config_get_global_field_name(unsigned int i, int *no_var)
   4439 {
   4440 	if (i >= NUM_GLOBAL_FIELDS)
   4441 		return NULL;
   4442 
   4443 	if (no_var)
   4444 		*no_var = !global_fields[i].param1;
   4445 	return global_fields[i].name;
   4446 }
   4447 
   4448 
   4449 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
   4450 {
   4451 	size_t i;
   4452 	int ret = 0;
   4453 
   4454 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   4455 		const struct global_parse_data *field = &global_fields[i];
   4456 		size_t flen = os_strlen(field->name);
   4457 		if (os_strncmp(pos, field->name, flen) != 0 ||
   4458 		    pos[flen] != '=')
   4459 			continue;
   4460 
   4461 		if (field->parser(field, config, line, pos + flen + 1)) {
   4462 			wpa_printf(MSG_ERROR, "Line %d: failed to "
   4463 				   "parse '%s'.", line, pos);
   4464 			ret = -1;
   4465 		}
   4466 		if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN)
   4467 			config->wps_nfc_pw_from_config = 1;
   4468 		config->changed_parameters |= field->changed_flag;
   4469 		break;
   4470 	}
   4471 	if (i == NUM_GLOBAL_FIELDS) {
   4472 #ifdef CONFIG_AP
   4473 		if (os_strncmp(pos, "wmm_ac_", 7) == 0) {
   4474 			char *tmp = os_strchr(pos, '=');
   4475 			if (tmp == NULL) {
   4476 				if (line < 0)
   4477 					return -1;
   4478 				wpa_printf(MSG_ERROR, "Line %d: invalid line "
   4479 					   "'%s'", line, pos);
   4480 				return -1;
   4481 			}
   4482 			*tmp++ = '\0';
   4483 			if (hostapd_config_wmm_ac(config->wmm_ac_params, pos,
   4484 						  tmp)) {
   4485 				wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
   4486 					   "AC item", line);
   4487 				return -1;
   4488 			}
   4489 		}
   4490 #endif /* CONFIG_AP */
   4491 		if (line < 0)
   4492 			return -1;
   4493 		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
   4494 			   line, pos);
   4495 		ret = -1;
   4496 	}
   4497 
   4498 	return ret;
   4499 }
   4500