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