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