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