Home | History | Annotate | Line # | Download | only in wpa_supplicant
config.c revision 1.1.1.1.12.2
      1 /*
      2  * WPA Supplicant / Configuration parser and common functions
      3  * Copyright (c) 2003-2012, 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 "crypto/sha1.h"
     14 #include "rsn_supp/wpa.h"
     15 #include "eap_peer/eap.h"
     16 #include "p2p/p2p.h"
     17 #include "config.h"
     18 
     19 
     20 #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
     21 #define NO_CONFIG_WRITE
     22 #endif
     23 
     24 /*
     25  * Structure for network configuration parsing. This data is used to implement
     26  * a generic parser for each network block variable. The table of configuration
     27  * variables is defined below in this file (ssid_fields[]).
     28  */
     29 struct parse_data {
     30 	/* Configuration variable name */
     31 	char *name;
     32 
     33 	/* Parser function for this variable */
     34 	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
     35 		      int line, const char *value);
     36 
     37 #ifndef NO_CONFIG_WRITE
     38 	/* Writer function (i.e., to get the variable in text format from
     39 	 * internal presentation). */
     40 	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
     41 #endif /* NO_CONFIG_WRITE */
     42 
     43 	/* Variable specific parameters for the parser. */
     44 	void *param1, *param2, *param3, *param4;
     45 
     46 	/* 0 = this variable can be included in debug output and ctrl_iface
     47 	 * 1 = this variable contains key/private data and it must not be
     48 	 *     included in debug output unless explicitly requested. In
     49 	 *     addition, this variable will not be readable through the
     50 	 *     ctrl_iface.
     51 	 */
     52 	int key_data;
     53 };
     54 
     55 
     56 static int wpa_config_parse_str(const struct parse_data *data,
     57 				struct wpa_ssid *ssid,
     58 				int line, const char *value)
     59 {
     60 	size_t res_len, *dst_len;
     61 	char **dst, *tmp;
     62 
     63 	if (os_strcmp(value, "NULL") == 0) {
     64 		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
     65 			   data->name);
     66 		tmp = NULL;
     67 		res_len = 0;
     68 		goto set;
     69 	}
     70 
     71 	tmp = wpa_config_parse_string(value, &res_len);
     72 	if (tmp == NULL) {
     73 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
     74 			   line, data->name,
     75 			   data->key_data ? "[KEY DATA REMOVED]" : value);
     76 		return -1;
     77 	}
     78 
     79 	if (data->key_data) {
     80 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
     81 				      (u8 *) tmp, res_len);
     82 	} else {
     83 		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
     84 				  (u8 *) tmp, res_len);
     85 	}
     86 
     87 	if (data->param3 && res_len < (size_t) data->param3) {
     88 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
     89 			   "min_len=%ld)", line, data->name,
     90 			   (unsigned long) res_len, (long) data->param3);
     91 		os_free(tmp);
     92 		return -1;
     93 	}
     94 
     95 	if (data->param4 && res_len > (size_t) data->param4) {
     96 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
     97 			   "max_len=%ld)", line, data->name,
     98 			   (unsigned long) res_len, (long) data->param4);
     99 		os_free(tmp);
    100 		return -1;
    101 	}
    102 
    103 set:
    104 	dst = (char **) (((u8 *) ssid) + (long) data->param1);
    105 	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
    106 	os_free(*dst);
    107 	*dst = tmp;
    108 	if (data->param2)
    109 		*dst_len = res_len;
    110 
    111 	return 0;
    112 }
    113 
    114 
    115 #ifndef NO_CONFIG_WRITE
    116 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
    117 {
    118 	char *buf;
    119 
    120 	buf = os_malloc(len + 3);
    121 	if (buf == NULL)
    122 		return NULL;
    123 	buf[0] = '"';
    124 	os_memcpy(buf + 1, value, len);
    125 	buf[len + 1] = '"';
    126 	buf[len + 2] = '\0';
    127 
    128 	return buf;
    129 }
    130 
    131 
    132 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
    133 {
    134 	char *buf;
    135 
    136 	buf = os_zalloc(2 * len + 1);
    137 	if (buf == NULL)
    138 		return NULL;
    139 	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
    140 
    141 	return buf;
    142 }
    143 
    144 
    145 static char * wpa_config_write_string(const u8 *value, size_t len)
    146 {
    147 	if (value == NULL)
    148 		return NULL;
    149 
    150 	if (is_hex(value, len))
    151 		return wpa_config_write_string_hex(value, len);
    152 	else
    153 		return wpa_config_write_string_ascii(value, len);
    154 }
    155 
    156 
    157 static char * wpa_config_write_str(const struct parse_data *data,
    158 				   struct wpa_ssid *ssid)
    159 {
    160 	size_t len;
    161 	char **src;
    162 
    163 	src = (char **) (((u8 *) ssid) + (long) data->param1);
    164 	if (*src == NULL)
    165 		return NULL;
    166 
    167 	if (data->param2)
    168 		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
    169 	else
    170 		len = os_strlen(*src);
    171 
    172 	return wpa_config_write_string((const u8 *) *src, len);
    173 }
    174 #endif /* NO_CONFIG_WRITE */
    175 
    176 
    177 static int wpa_config_parse_int(const struct parse_data *data,
    178 				struct wpa_ssid *ssid,
    179 				int line, const char *value)
    180 {
    181 	int *dst;
    182 
    183 	dst = (int *) (((u8 *) ssid) + (long) data->param1);
    184 	*dst = atoi(value);
    185 	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
    186 
    187 	if (data->param3 && *dst < (long) data->param3) {
    188 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
    189 			   "min_value=%ld)", line, data->name, *dst,
    190 			   (long) data->param3);
    191 		*dst = (long) data->param3;
    192 		return -1;
    193 	}
    194 
    195 	if (data->param4 && *dst > (long) data->param4) {
    196 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
    197 			   "max_value=%ld)", line, data->name, *dst,
    198 			   (long) data->param4);
    199 		*dst = (long) data->param4;
    200 		return -1;
    201 	}
    202 
    203 	return 0;
    204 }
    205 
    206 
    207 #ifndef NO_CONFIG_WRITE
    208 static char * wpa_config_write_int(const struct parse_data *data,
    209 				   struct wpa_ssid *ssid)
    210 {
    211 	int *src, res;
    212 	char *value;
    213 
    214 	src = (int *) (((u8 *) ssid) + (long) data->param1);
    215 
    216 	value = os_malloc(20);
    217 	if (value == NULL)
    218 		return NULL;
    219 	res = os_snprintf(value, 20, "%d", *src);
    220 	if (res < 0 || res >= 20) {
    221 		os_free(value);
    222 		return NULL;
    223 	}
    224 	value[20 - 1] = '\0';
    225 	return value;
    226 }
    227 #endif /* NO_CONFIG_WRITE */
    228 
    229 
    230 static int wpa_config_parse_bssid(const struct parse_data *data,
    231 				  struct wpa_ssid *ssid, int line,
    232 				  const char *value)
    233 {
    234 	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
    235 	    os_strcmp(value, "any") == 0) {
    236 		ssid->bssid_set = 0;
    237 		wpa_printf(MSG_MSGDUMP, "BSSID any");
    238 		return 0;
    239 	}
    240 	if (hwaddr_aton(value, ssid->bssid)) {
    241 		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
    242 			   line, value);
    243 		return -1;
    244 	}
    245 	ssid->bssid_set = 1;
    246 	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
    247 	return 0;
    248 }
    249 
    250 
    251 #ifndef NO_CONFIG_WRITE
    252 static char * wpa_config_write_bssid(const struct parse_data *data,
    253 				     struct wpa_ssid *ssid)
    254 {
    255 	char *value;
    256 	int res;
    257 
    258 	if (!ssid->bssid_set)
    259 		return NULL;
    260 
    261 	value = os_malloc(20);
    262 	if (value == NULL)
    263 		return NULL;
    264 	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
    265 	if (res < 0 || res >= 20) {
    266 		os_free(value);
    267 		return NULL;
    268 	}
    269 	value[20 - 1] = '\0';
    270 	return value;
    271 }
    272 #endif /* NO_CONFIG_WRITE */
    273 
    274 
    275 static int wpa_config_parse_psk(const struct parse_data *data,
    276 				struct wpa_ssid *ssid, int line,
    277 				const char *value)
    278 {
    279 #ifdef CONFIG_EXT_PASSWORD
    280 	if (os_strncmp(value, "ext:", 4) == 0) {
    281 		os_free(ssid->passphrase);
    282 		ssid->passphrase = NULL;
    283 		ssid->psk_set = 0;
    284 		os_free(ssid->ext_psk);
    285 		ssid->ext_psk = os_strdup(value + 4);
    286 		if (ssid->ext_psk == NULL)
    287 			return -1;
    288 		wpa_printf(MSG_DEBUG, "PSK: External password '%s'",
    289 			   ssid->ext_psk);
    290 		return 0;
    291 	}
    292 #endif /* CONFIG_EXT_PASSWORD */
    293 
    294 	if (*value == '"') {
    295 #ifndef CONFIG_NO_PBKDF2
    296 		const char *pos;
    297 		size_t len;
    298 
    299 		value++;
    300 		pos = os_strrchr(value, '"');
    301 		if (pos)
    302 			len = pos - value;
    303 		else
    304 			len = os_strlen(value);
    305 		if (len < 8 || len > 63) {
    306 			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
    307 				   "length %lu (expected: 8..63) '%s'.",
    308 				   line, (unsigned long) len, value);
    309 			return -1;
    310 		}
    311 		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
    312 				      (u8 *) value, len);
    313 		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
    314 		    os_memcmp(ssid->passphrase, value, len) == 0)
    315 			return 0;
    316 		ssid->psk_set = 0;
    317 		os_free(ssid->passphrase);
    318 		ssid->passphrase = os_malloc(len + 1);
    319 		if (ssid->passphrase == NULL)
    320 			return -1;
    321 		os_memcpy(ssid->passphrase, value, len);
    322 		ssid->passphrase[len] = '\0';
    323 		return 0;
    324 #else /* CONFIG_NO_PBKDF2 */
    325 		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
    326 			   "supported.", line);
    327 		return -1;
    328 #endif /* CONFIG_NO_PBKDF2 */
    329 	}
    330 
    331 	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
    332 	    value[PMK_LEN * 2] != '\0') {
    333 		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
    334 			   line, value);
    335 		return -1;
    336 	}
    337 
    338 	os_free(ssid->passphrase);
    339 	ssid->passphrase = NULL;
    340 
    341 	ssid->psk_set = 1;
    342 	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
    343 	return 0;
    344 }
    345 
    346 
    347 #ifndef NO_CONFIG_WRITE
    348 static char * wpa_config_write_psk(const struct parse_data *data,
    349 				   struct wpa_ssid *ssid)
    350 {
    351 #ifdef CONFIG_EXT_PASSWORD
    352 	if (ssid->ext_psk) {
    353 		size_t len = 4 + os_strlen(ssid->ext_psk) + 1;
    354 		char *buf = os_malloc(len);
    355 		if (buf == NULL)
    356 			return NULL;
    357 		os_snprintf(buf, len, "ext:%s", ssid->ext_psk);
    358 		return buf;
    359 	}
    360 #endif /* CONFIG_EXT_PASSWORD */
    361 
    362 	if (ssid->passphrase)
    363 		return wpa_config_write_string_ascii(
    364 			(const u8 *) ssid->passphrase,
    365 			os_strlen(ssid->passphrase));
    366 
    367 	if (ssid->psk_set)
    368 		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
    369 
    370 	return NULL;
    371 }
    372 #endif /* NO_CONFIG_WRITE */
    373 
    374 
    375 static int wpa_config_parse_proto(const struct parse_data *data,
    376 				  struct wpa_ssid *ssid, int line,
    377 				  const char *value)
    378 {
    379 	int val = 0, last, errors = 0;
    380 	char *start, *end, *buf;
    381 
    382 	buf = os_strdup(value);
    383 	if (buf == NULL)
    384 		return -1;
    385 	start = buf;
    386 
    387 	while (*start != '\0') {
    388 		while (*start == ' ' || *start == '\t')
    389 			start++;
    390 		if (*start == '\0')
    391 			break;
    392 		end = start;
    393 		while (*end != ' ' && *end != '\t' && *end != '\0')
    394 			end++;
    395 		last = *end == '\0';
    396 		*end = '\0';
    397 		if (os_strcmp(start, "WPA") == 0)
    398 			val |= WPA_PROTO_WPA;
    399 		else if (os_strcmp(start, "RSN") == 0 ||
    400 			 os_strcmp(start, "WPA2") == 0)
    401 			val |= WPA_PROTO_RSN;
    402 		else {
    403 			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
    404 				   line, start);
    405 			errors++;
    406 		}
    407 
    408 		if (last)
    409 			break;
    410 		start = end + 1;
    411 	}
    412 	os_free(buf);
    413 
    414 	if (val == 0) {
    415 		wpa_printf(MSG_ERROR,
    416 			   "Line %d: no proto values configured.", line);
    417 		errors++;
    418 	}
    419 
    420 	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
    421 	ssid->proto = val;
    422 	return errors ? -1 : 0;
    423 }
    424 
    425 
    426 #ifndef NO_CONFIG_WRITE
    427 static char * wpa_config_write_proto(const struct parse_data *data,
    428 				     struct wpa_ssid *ssid)
    429 {
    430 	int first = 1, ret;
    431 	char *buf, *pos, *end;
    432 
    433 	pos = buf = os_zalloc(10);
    434 	if (buf == NULL)
    435 		return NULL;
    436 	end = buf + 10;
    437 
    438 	if (ssid->proto & WPA_PROTO_WPA) {
    439 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
    440 		if (ret < 0 || ret >= end - pos)
    441 			return buf;
    442 		pos += ret;
    443 		first = 0;
    444 	}
    445 
    446 	if (ssid->proto & WPA_PROTO_RSN) {
    447 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
    448 		if (ret < 0 || ret >= end - pos)
    449 			return buf;
    450 		pos += ret;
    451 		first = 0;
    452 	}
    453 
    454 	return buf;
    455 }
    456 #endif /* NO_CONFIG_WRITE */
    457 
    458 
    459 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
    460 				     struct wpa_ssid *ssid, int line,
    461 				     const char *value)
    462 {
    463 	int val = 0, last, errors = 0;
    464 	char *start, *end, *buf;
    465 
    466 	buf = os_strdup(value);
    467 	if (buf == NULL)
    468 		return -1;
    469 	start = buf;
    470 
    471 	while (*start != '\0') {
    472 		while (*start == ' ' || *start == '\t')
    473 			start++;
    474 		if (*start == '\0')
    475 			break;
    476 		end = start;
    477 		while (*end != ' ' && *end != '\t' && *end != '\0')
    478 			end++;
    479 		last = *end == '\0';
    480 		*end = '\0';
    481 		if (os_strcmp(start, "WPA-PSK") == 0)
    482 			val |= WPA_KEY_MGMT_PSK;
    483 		else if (os_strcmp(start, "WPA-EAP") == 0)
    484 			val |= WPA_KEY_MGMT_IEEE8021X;
    485 		else if (os_strcmp(start, "IEEE8021X") == 0)
    486 			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
    487 		else if (os_strcmp(start, "NONE") == 0)
    488 			val |= WPA_KEY_MGMT_NONE;
    489 		else if (os_strcmp(start, "WPA-NONE") == 0)
    490 			val |= WPA_KEY_MGMT_WPA_NONE;
    491 #ifdef CONFIG_IEEE80211R
    492 		else if (os_strcmp(start, "FT-PSK") == 0)
    493 			val |= WPA_KEY_MGMT_FT_PSK;
    494 		else if (os_strcmp(start, "FT-EAP") == 0)
    495 			val |= WPA_KEY_MGMT_FT_IEEE8021X;
    496 #endif /* CONFIG_IEEE80211R */
    497 #ifdef CONFIG_IEEE80211W
    498 		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
    499 			val |= WPA_KEY_MGMT_PSK_SHA256;
    500 		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
    501 			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
    502 #endif /* CONFIG_IEEE80211W */
    503 #ifdef CONFIG_WPS
    504 		else if (os_strcmp(start, "WPS") == 0)
    505 			val |= WPA_KEY_MGMT_WPS;
    506 #endif /* CONFIG_WPS */
    507 #ifdef CONFIG_SAE
    508 		else if (os_strcmp(start, "SAE") == 0)
    509 			val |= WPA_KEY_MGMT_SAE;
    510 		else if (os_strcmp(start, "FT-SAE") == 0)
    511 			val |= WPA_KEY_MGMT_FT_SAE;
    512 #endif /* CONFIG_SAE */
    513 		else {
    514 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
    515 				   line, start);
    516 			errors++;
    517 		}
    518 
    519 		if (last)
    520 			break;
    521 		start = end + 1;
    522 	}
    523 	os_free(buf);
    524 
    525 	if (val == 0) {
    526 		wpa_printf(MSG_ERROR,
    527 			   "Line %d: no key_mgmt values configured.", line);
    528 		errors++;
    529 	}
    530 
    531 	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
    532 	ssid->key_mgmt = val;
    533 	return errors ? -1 : 0;
    534 }
    535 
    536 
    537 #ifndef NO_CONFIG_WRITE
    538 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
    539 					struct wpa_ssid *ssid)
    540 {
    541 	char *buf, *pos, *end;
    542 	int ret;
    543 
    544 	pos = buf = os_zalloc(50);
    545 	if (buf == NULL)
    546 		return NULL;
    547 	end = buf + 50;
    548 
    549 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
    550 		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
    551 				  pos == buf ? "" : " ");
    552 		if (ret < 0 || ret >= end - pos) {
    553 			end[-1] = '\0';
    554 			return buf;
    555 		}
    556 		pos += ret;
    557 	}
    558 
    559 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    560 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
    561 				  pos == buf ? "" : " ");
    562 		if (ret < 0 || ret >= end - pos) {
    563 			end[-1] = '\0';
    564 			return buf;
    565 		}
    566 		pos += ret;
    567 	}
    568 
    569 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    570 		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
    571 				  pos == buf ? "" : " ");
    572 		if (ret < 0 || ret >= end - pos) {
    573 			end[-1] = '\0';
    574 			return buf;
    575 		}
    576 		pos += ret;
    577 	}
    578 
    579 	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
    580 		ret = os_snprintf(pos, end - pos, "%sNONE",
    581 				  pos == buf ? "" : " ");
    582 		if (ret < 0 || ret >= end - pos) {
    583 			end[-1] = '\0';
    584 			return buf;
    585 		}
    586 		pos += ret;
    587 	}
    588 
    589 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    590 		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
    591 				  pos == buf ? "" : " ");
    592 		if (ret < 0 || ret >= end - pos) {
    593 			end[-1] = '\0';
    594 			return buf;
    595 		}
    596 		pos += ret;
    597 	}
    598 
    599 #ifdef CONFIG_IEEE80211R
    600 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
    601 		pos += os_snprintf(pos, end - pos, "%sFT-PSK",
    602 				   pos == buf ? "" : " ");
    603 
    604 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
    605 		pos += os_snprintf(pos, end - pos, "%sFT-EAP",
    606 				   pos == buf ? "" : " ");
    607 #endif /* CONFIG_IEEE80211R */
    608 
    609 #ifdef CONFIG_IEEE80211W
    610 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
    611 		pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
    612 				   pos == buf ? "" : " ");
    613 
    614 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
    615 		pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
    616 				   pos == buf ? "" : " ");
    617 #endif /* CONFIG_IEEE80211W */
    618 
    619 #ifdef CONFIG_WPS
    620 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
    621 		pos += os_snprintf(pos, end - pos, "%sWPS",
    622 				   pos == buf ? "" : " ");
    623 #endif /* CONFIG_WPS */
    624 
    625 	return buf;
    626 }
    627 #endif /* NO_CONFIG_WRITE */
    628 
    629 
    630 static int wpa_config_parse_cipher(int line, const char *value)
    631 {
    632 	int val = 0, last;
    633 	char *start, *end, *buf;
    634 
    635 	buf = os_strdup(value);
    636 	if (buf == NULL)
    637 		return -1;
    638 	start = buf;
    639 
    640 	while (*start != '\0') {
    641 		while (*start == ' ' || *start == '\t')
    642 			start++;
    643 		if (*start == '\0')
    644 			break;
    645 		end = start;
    646 		while (*end != ' ' && *end != '\t' && *end != '\0')
    647 			end++;
    648 		last = *end == '\0';
    649 		*end = '\0';
    650 		if (os_strcmp(start, "CCMP") == 0)
    651 			val |= WPA_CIPHER_CCMP;
    652 		else if (os_strcmp(start, "GCMP") == 0)
    653 			val |= WPA_CIPHER_GCMP;
    654 		else if (os_strcmp(start, "TKIP") == 0)
    655 			val |= WPA_CIPHER_TKIP;
    656 		else if (os_strcmp(start, "WEP104") == 0)
    657 			val |= WPA_CIPHER_WEP104;
    658 		else if (os_strcmp(start, "WEP40") == 0)
    659 			val |= WPA_CIPHER_WEP40;
    660 		else if (os_strcmp(start, "NONE") == 0)
    661 			val |= WPA_CIPHER_NONE;
    662 		else {
    663 			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
    664 				   line, start);
    665 			os_free(buf);
    666 			return -1;
    667 		}
    668 
    669 		if (last)
    670 			break;
    671 		start = end + 1;
    672 	}
    673 	os_free(buf);
    674 
    675 	if (val == 0) {
    676 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
    677 			   line);
    678 		return -1;
    679 	}
    680 	return val;
    681 }
    682 
    683 
    684 #ifndef NO_CONFIG_WRITE
    685 static char * wpa_config_write_cipher(int cipher)
    686 {
    687 	char *buf, *pos, *end;
    688 	int ret;
    689 
    690 	pos = buf = os_zalloc(50);
    691 	if (buf == NULL)
    692 		return NULL;
    693 	end = buf + 50;
    694 
    695 	if (cipher & WPA_CIPHER_CCMP) {
    696 		ret = os_snprintf(pos, end - pos, "%sCCMP",
    697 				  pos == buf ? "" : " ");
    698 		if (ret < 0 || ret >= end - pos) {
    699 			end[-1] = '\0';
    700 			return buf;
    701 		}
    702 		pos += ret;
    703 	}
    704 
    705 	if (cipher & WPA_CIPHER_GCMP) {
    706 		ret = os_snprintf(pos, end - pos, "%sGCMP",
    707 				  pos == buf ? "" : " ");
    708 		if (ret < 0 || ret >= end - pos) {
    709 			end[-1] = '\0';
    710 			return buf;
    711 		}
    712 		pos += ret;
    713 	}
    714 
    715 	if (cipher & WPA_CIPHER_TKIP) {
    716 		ret = os_snprintf(pos, end - pos, "%sTKIP",
    717 				  pos == buf ? "" : " ");
    718 		if (ret < 0 || ret >= end - pos) {
    719 			end[-1] = '\0';
    720 			return buf;
    721 		}
    722 		pos += ret;
    723 	}
    724 
    725 	if (cipher & WPA_CIPHER_WEP104) {
    726 		ret = os_snprintf(pos, end - pos, "%sWEP104",
    727 				  pos == buf ? "" : " ");
    728 		if (ret < 0 || ret >= end - pos) {
    729 			end[-1] = '\0';
    730 			return buf;
    731 		}
    732 		pos += ret;
    733 	}
    734 
    735 	if (cipher & WPA_CIPHER_WEP40) {
    736 		ret = os_snprintf(pos, end - pos, "%sWEP40",
    737 				  pos == buf ? "" : " ");
    738 		if (ret < 0 || ret >= end - pos) {
    739 			end[-1] = '\0';
    740 			return buf;
    741 		}
    742 		pos += ret;
    743 	}
    744 
    745 	if (cipher & WPA_CIPHER_NONE) {
    746 		ret = os_snprintf(pos, end - pos, "%sNONE",
    747 				  pos == buf ? "" : " ");
    748 		if (ret < 0 || ret >= end - pos) {
    749 			end[-1] = '\0';
    750 			return buf;
    751 		}
    752 		pos += ret;
    753 	}
    754 
    755 	return buf;
    756 }
    757 #endif /* NO_CONFIG_WRITE */
    758 
    759 
    760 static int wpa_config_parse_pairwise(const struct parse_data *data,
    761 				     struct wpa_ssid *ssid, int line,
    762 				     const char *value)
    763 {
    764 	int val;
    765 	val = wpa_config_parse_cipher(line, value);
    766 	if (val == -1)
    767 		return -1;
    768 	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP |
    769 		    WPA_CIPHER_NONE)) {
    770 		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
    771 			   "(0x%x).", line, val);
    772 		return -1;
    773 	}
    774 
    775 	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
    776 	ssid->pairwise_cipher = val;
    777 	return 0;
    778 }
    779 
    780 
    781 #ifndef NO_CONFIG_WRITE
    782 static char * wpa_config_write_pairwise(const struct parse_data *data,
    783 					struct wpa_ssid *ssid)
    784 {
    785 	return wpa_config_write_cipher(ssid->pairwise_cipher);
    786 }
    787 #endif /* NO_CONFIG_WRITE */
    788 
    789 
    790 static int wpa_config_parse_group(const struct parse_data *data,
    791 				  struct wpa_ssid *ssid, int line,
    792 				  const char *value)
    793 {
    794 	int val;
    795 	val = wpa_config_parse_cipher(line, value);
    796 	if (val == -1)
    797 		return -1;
    798 	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP |
    799 		    WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) {
    800 		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
    801 			   "(0x%x).", line, val);
    802 		return -1;
    803 	}
    804 
    805 	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
    806 	ssid->group_cipher = val;
    807 	return 0;
    808 }
    809 
    810 
    811 #ifndef NO_CONFIG_WRITE
    812 static char * wpa_config_write_group(const struct parse_data *data,
    813 				     struct wpa_ssid *ssid)
    814 {
    815 	return wpa_config_write_cipher(ssid->group_cipher);
    816 }
    817 #endif /* NO_CONFIG_WRITE */
    818 
    819 
    820 static int wpa_config_parse_auth_alg(const struct parse_data *data,
    821 				     struct wpa_ssid *ssid, int line,
    822 				     const char *value)
    823 {
    824 	int val = 0, last, errors = 0;
    825 	char *start, *end, *buf;
    826 
    827 	buf = os_strdup(value);
    828 	if (buf == NULL)
    829 		return -1;
    830 	start = buf;
    831 
    832 	while (*start != '\0') {
    833 		while (*start == ' ' || *start == '\t')
    834 			start++;
    835 		if (*start == '\0')
    836 			break;
    837 		end = start;
    838 		while (*end != ' ' && *end != '\t' && *end != '\0')
    839 			end++;
    840 		last = *end == '\0';
    841 		*end = '\0';
    842 		if (os_strcmp(start, "OPEN") == 0)
    843 			val |= WPA_AUTH_ALG_OPEN;
    844 		else if (os_strcmp(start, "SHARED") == 0)
    845 			val |= WPA_AUTH_ALG_SHARED;
    846 		else if (os_strcmp(start, "LEAP") == 0)
    847 			val |= WPA_AUTH_ALG_LEAP;
    848 		else {
    849 			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
    850 				   line, start);
    851 			errors++;
    852 		}
    853 
    854 		if (last)
    855 			break;
    856 		start = end + 1;
    857 	}
    858 	os_free(buf);
    859 
    860 	if (val == 0) {
    861 		wpa_printf(MSG_ERROR,
    862 			   "Line %d: no auth_alg values configured.", line);
    863 		errors++;
    864 	}
    865 
    866 	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
    867 	ssid->auth_alg = val;
    868 	return errors ? -1 : 0;
    869 }
    870 
    871 
    872 #ifndef NO_CONFIG_WRITE
    873 static char * wpa_config_write_auth_alg(const struct parse_data *data,
    874 					struct wpa_ssid *ssid)
    875 {
    876 	char *buf, *pos, *end;
    877 	int ret;
    878 
    879 	pos = buf = os_zalloc(30);
    880 	if (buf == NULL)
    881 		return NULL;
    882 	end = buf + 30;
    883 
    884 	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
    885 		ret = os_snprintf(pos, end - pos, "%sOPEN",
    886 				  pos == buf ? "" : " ");
    887 		if (ret < 0 || ret >= end - pos) {
    888 			end[-1] = '\0';
    889 			return buf;
    890 		}
    891 		pos += ret;
    892 	}
    893 
    894 	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
    895 		ret = os_snprintf(pos, end - pos, "%sSHARED",
    896 				  pos == buf ? "" : " ");
    897 		if (ret < 0 || ret >= end - pos) {
    898 			end[-1] = '\0';
    899 			return buf;
    900 		}
    901 		pos += ret;
    902 	}
    903 
    904 	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
    905 		ret = os_snprintf(pos, end - pos, "%sLEAP",
    906 				  pos == buf ? "" : " ");
    907 		if (ret < 0 || ret >= end - pos) {
    908 			end[-1] = '\0';
    909 			return buf;
    910 		}
    911 		pos += ret;
    912 	}
    913 
    914 	return buf;
    915 }
    916 #endif /* NO_CONFIG_WRITE */
    917 
    918 
    919 static int * wpa_config_parse_freqs(const struct parse_data *data,
    920 				    struct wpa_ssid *ssid, int line,
    921 				    const char *value)
    922 {
    923 	int *freqs;
    924 	size_t used, len;
    925 	const char *pos;
    926 
    927 	used = 0;
    928 	len = 10;
    929 	freqs = os_calloc(len + 1, sizeof(int));
    930 	if (freqs == NULL)
    931 		return NULL;
    932 
    933 	pos = value;
    934 	while (pos) {
    935 		while (*pos == ' ')
    936 			pos++;
    937 		if (used == len) {
    938 			int *n;
    939 			size_t i;
    940 			n = os_realloc_array(freqs, len * 2 + 1, sizeof(int));
    941 			if (n == NULL) {
    942 				os_free(freqs);
    943 				return NULL;
    944 			}
    945 			for (i = len; i <= len * 2; i++)
    946 				n[i] = 0;
    947 			freqs = n;
    948 			len *= 2;
    949 		}
    950 
    951 		freqs[used] = atoi(pos);
    952 		if (freqs[used] == 0)
    953 			break;
    954 		used++;
    955 		pos = os_strchr(pos + 1, ' ');
    956 	}
    957 
    958 	return freqs;
    959 }
    960 
    961 
    962 static int wpa_config_parse_scan_freq(const struct parse_data *data,
    963 				      struct wpa_ssid *ssid, int line,
    964 				      const char *value)
    965 {
    966 	int *freqs;
    967 
    968 	freqs = wpa_config_parse_freqs(data, ssid, line, value);
    969 	if (freqs == NULL)
    970 		return -1;
    971 	os_free(ssid->scan_freq);
    972 	ssid->scan_freq = freqs;
    973 
    974 	return 0;
    975 }
    976 
    977 
    978 static int wpa_config_parse_freq_list(const struct parse_data *data,
    979 				      struct wpa_ssid *ssid, int line,
    980 				      const char *value)
    981 {
    982 	int *freqs;
    983 
    984 	freqs = wpa_config_parse_freqs(data, ssid, line, value);
    985 	if (freqs == NULL)
    986 		return -1;
    987 	os_free(ssid->freq_list);
    988 	ssid->freq_list = freqs;
    989 
    990 	return 0;
    991 }
    992 
    993 
    994 #ifndef NO_CONFIG_WRITE
    995 static char * wpa_config_write_freqs(const struct parse_data *data,
    996 				     const int *freqs)
    997 {
    998 	char *buf, *pos, *end;
    999 	int i, ret;
   1000 	size_t count;
   1001 
   1002 	if (freqs == NULL)
   1003 		return NULL;
   1004 
   1005 	count = 0;
   1006 	for (i = 0; freqs[i]; i++)
   1007 		count++;
   1008 
   1009 	pos = buf = os_zalloc(10 * count + 1);
   1010 	if (buf == NULL)
   1011 		return NULL;
   1012 	end = buf + 10 * count + 1;
   1013 
   1014 	for (i = 0; freqs[i]; i++) {
   1015 		ret = os_snprintf(pos, end - pos, "%s%u",
   1016 				  i == 0 ? "" : " ", freqs[i]);
   1017 		if (ret < 0 || ret >= end - pos) {
   1018 			end[-1] = '\0';
   1019 			return buf;
   1020 		}
   1021 		pos += ret;
   1022 	}
   1023 
   1024 	return buf;
   1025 }
   1026 
   1027 
   1028 static char * wpa_config_write_scan_freq(const struct parse_data *data,
   1029 					 struct wpa_ssid *ssid)
   1030 {
   1031 	return wpa_config_write_freqs(data, ssid->scan_freq);
   1032 }
   1033 
   1034 
   1035 static char * wpa_config_write_freq_list(const struct parse_data *data,
   1036 					 struct wpa_ssid *ssid)
   1037 {
   1038 	return wpa_config_write_freqs(data, ssid->freq_list);
   1039 }
   1040 #endif /* NO_CONFIG_WRITE */
   1041 
   1042 
   1043 #ifdef IEEE8021X_EAPOL
   1044 static int wpa_config_parse_eap(const struct parse_data *data,
   1045 				struct wpa_ssid *ssid, int line,
   1046 				const char *value)
   1047 {
   1048 	int last, errors = 0;
   1049 	char *start, *end, *buf;
   1050 	struct eap_method_type *methods = NULL, *tmp;
   1051 	size_t num_methods = 0;
   1052 
   1053 	buf = os_strdup(value);
   1054 	if (buf == NULL)
   1055 		return -1;
   1056 	start = buf;
   1057 
   1058 	while (*start != '\0') {
   1059 		while (*start == ' ' || *start == '\t')
   1060 			start++;
   1061 		if (*start == '\0')
   1062 			break;
   1063 		end = start;
   1064 		while (*end != ' ' && *end != '\t' && *end != '\0')
   1065 			end++;
   1066 		last = *end == '\0';
   1067 		*end = '\0';
   1068 		tmp = methods;
   1069 		methods = os_realloc_array(methods, num_methods + 1,
   1070 					   sizeof(*methods));
   1071 		if (methods == NULL) {
   1072 			os_free(tmp);
   1073 			os_free(buf);
   1074 			return -1;
   1075 		}
   1076 		methods[num_methods].method = eap_peer_get_type(
   1077 			start, &methods[num_methods].vendor);
   1078 		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
   1079 		    methods[num_methods].method == EAP_TYPE_NONE) {
   1080 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
   1081 				   "'%s'", line, start);
   1082 			wpa_printf(MSG_ERROR, "You may need to add support for"
   1083 				   " this EAP method during wpa_supplicant\n"
   1084 				   "build time configuration.\n"
   1085 				   "See README for more information.");
   1086 			errors++;
   1087 		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
   1088 			   methods[num_methods].method == EAP_TYPE_LEAP)
   1089 			ssid->leap++;
   1090 		else
   1091 			ssid->non_leap++;
   1092 		num_methods++;
   1093 		if (last)
   1094 			break;
   1095 		start = end + 1;
   1096 	}
   1097 	os_free(buf);
   1098 
   1099 	tmp = methods;
   1100 	methods = os_realloc_array(methods, num_methods + 1, sizeof(*methods));
   1101 	if (methods == NULL) {
   1102 		os_free(tmp);
   1103 		return -1;
   1104 	}
   1105 	methods[num_methods].vendor = EAP_VENDOR_IETF;
   1106 	methods[num_methods].method = EAP_TYPE_NONE;
   1107 	num_methods++;
   1108 
   1109 	wpa_hexdump(MSG_MSGDUMP, "eap methods",
   1110 		    (u8 *) methods, num_methods * sizeof(*methods));
   1111 	os_free(ssid->eap.eap_methods);
   1112 	ssid->eap.eap_methods = methods;
   1113 	return errors ? -1 : 0;
   1114 }
   1115 
   1116 
   1117 static char * wpa_config_write_eap(const struct parse_data *data,
   1118 				   struct wpa_ssid *ssid)
   1119 {
   1120 	int i, ret;
   1121 	char *buf, *pos, *end;
   1122 	const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
   1123 	const char *name;
   1124 
   1125 	if (eap_methods == NULL)
   1126 		return NULL;
   1127 
   1128 	pos = buf = os_zalloc(100);
   1129 	if (buf == NULL)
   1130 		return NULL;
   1131 	end = buf + 100;
   1132 
   1133 	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
   1134 		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
   1135 		name = eap_get_name(eap_methods[i].vendor,
   1136 				    eap_methods[i].method);
   1137 		if (name) {
   1138 			ret = os_snprintf(pos, end - pos, "%s%s",
   1139 					  pos == buf ? "" : " ", name);
   1140 			if (ret < 0 || ret >= end - pos)
   1141 				break;
   1142 			pos += ret;
   1143 		}
   1144 	}
   1145 
   1146 	end[-1] = '\0';
   1147 
   1148 	return buf;
   1149 }
   1150 
   1151 
   1152 static int wpa_config_parse_password(const struct parse_data *data,
   1153 				     struct wpa_ssid *ssid, int line,
   1154 				     const char *value)
   1155 {
   1156 	u8 *hash;
   1157 
   1158 	if (os_strcmp(value, "NULL") == 0) {
   1159 		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
   1160 		os_free(ssid->eap.password);
   1161 		ssid->eap.password = NULL;
   1162 		ssid->eap.password_len = 0;
   1163 		return 0;
   1164 	}
   1165 
   1166 #ifdef CONFIG_EXT_PASSWORD
   1167 	if (os_strncmp(value, "ext:", 4) == 0) {
   1168 		char *name = os_strdup(value + 4);
   1169 		if (name == NULL)
   1170 			return -1;
   1171 		os_free(ssid->eap.password);
   1172 		ssid->eap.password = (u8 *) name;
   1173 		ssid->eap.password_len = os_strlen(name);
   1174 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1175 		ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1176 		return 0;
   1177 	}
   1178 #endif /* CONFIG_EXT_PASSWORD */
   1179 
   1180 	if (os_strncmp(value, "hash:", 5) != 0) {
   1181 		char *tmp;
   1182 		size_t res_len;
   1183 
   1184 		tmp = wpa_config_parse_string(value, &res_len);
   1185 		if (tmp == NULL) {
   1186 			wpa_printf(MSG_ERROR, "Line %d: failed to parse "
   1187 				   "password.", line);
   1188 			return -1;
   1189 		}
   1190 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
   1191 				      (u8 *) tmp, res_len);
   1192 
   1193 		os_free(ssid->eap.password);
   1194 		ssid->eap.password = (u8 *) tmp;
   1195 		ssid->eap.password_len = res_len;
   1196 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1197 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1198 
   1199 		return 0;
   1200 	}
   1201 
   1202 
   1203 	/* NtPasswordHash: hash:<32 hex digits> */
   1204 	if (os_strlen(value + 5) != 2 * 16) {
   1205 		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
   1206 			   "(expected 32 hex digits)", line);
   1207 		return -1;
   1208 	}
   1209 
   1210 	hash = os_malloc(16);
   1211 	if (hash == NULL)
   1212 		return -1;
   1213 
   1214 	if (hexstr2bin(value + 5, hash, 16)) {
   1215 		os_free(hash);
   1216 		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
   1217 		return -1;
   1218 	}
   1219 
   1220 	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
   1221 
   1222 	os_free(ssid->eap.password);
   1223 	ssid->eap.password = hash;
   1224 	ssid->eap.password_len = 16;
   1225 	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1226 	ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1227 
   1228 	return 0;
   1229 }
   1230 
   1231 
   1232 static char * wpa_config_write_password(const struct parse_data *data,
   1233 					struct wpa_ssid *ssid)
   1234 {
   1235 	char *buf;
   1236 
   1237 	if (ssid->eap.password == NULL)
   1238 		return NULL;
   1239 
   1240 #ifdef CONFIG_EXT_PASSWORD
   1241 	if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
   1242 		buf = os_zalloc(4 + ssid->eap.password_len + 1);
   1243 		if (buf == NULL)
   1244 			return NULL;
   1245 		os_memcpy(buf, "ext:", 4);
   1246 		os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
   1247 		return buf;
   1248 	}
   1249 #endif /* CONFIG_EXT_PASSWORD */
   1250 
   1251 	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
   1252 		return wpa_config_write_string(
   1253 			ssid->eap.password, ssid->eap.password_len);
   1254 	}
   1255 
   1256 	buf = os_malloc(5 + 32 + 1);
   1257 	if (buf == NULL)
   1258 		return NULL;
   1259 
   1260 	os_memcpy(buf, "hash:", 5);
   1261 	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
   1262 
   1263 	return buf;
   1264 }
   1265 #endif /* IEEE8021X_EAPOL */
   1266 
   1267 
   1268 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
   1269 				    const char *value, int idx)
   1270 {
   1271 	char *buf, title[20];
   1272 	int res;
   1273 
   1274 	buf = wpa_config_parse_string(value, len);
   1275 	if (buf == NULL) {
   1276 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
   1277 			   line, idx, value);
   1278 		return -1;
   1279 	}
   1280 	if (*len > MAX_WEP_KEY_LEN) {
   1281 		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
   1282 			   line, idx, value);
   1283 		os_free(buf);
   1284 		return -1;
   1285 	}
   1286 	if (*len && *len != 5 && *len != 13 && *len != 16) {
   1287 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - "
   1288 			   "this network block will be ignored",
   1289 			   line, (unsigned int) *len);
   1290 	}
   1291 	os_memcpy(key, buf, *len);
   1292 	os_free(buf);
   1293 	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
   1294 	if (res >= 0 && (size_t) res < sizeof(title))
   1295 		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
   1296 	return 0;
   1297 }
   1298 
   1299 
   1300 static int wpa_config_parse_wep_key0(const struct parse_data *data,
   1301 				     struct wpa_ssid *ssid, int line,
   1302 				     const char *value)
   1303 {
   1304 	return wpa_config_parse_wep_key(ssid->wep_key[0],
   1305 					&ssid->wep_key_len[0], line,
   1306 					value, 0);
   1307 }
   1308 
   1309 
   1310 static int wpa_config_parse_wep_key1(const struct parse_data *data,
   1311 				     struct wpa_ssid *ssid, int line,
   1312 				     const char *value)
   1313 {
   1314 	return wpa_config_parse_wep_key(ssid->wep_key[1],
   1315 					&ssid->wep_key_len[1], line,
   1316 					value, 1);
   1317 }
   1318 
   1319 
   1320 static int wpa_config_parse_wep_key2(const struct parse_data *data,
   1321 				     struct wpa_ssid *ssid, int line,
   1322 				     const char *value)
   1323 {
   1324 	return wpa_config_parse_wep_key(ssid->wep_key[2],
   1325 					&ssid->wep_key_len[2], line,
   1326 					value, 2);
   1327 }
   1328 
   1329 
   1330 static int wpa_config_parse_wep_key3(const struct parse_data *data,
   1331 				     struct wpa_ssid *ssid, int line,
   1332 				     const char *value)
   1333 {
   1334 	return wpa_config_parse_wep_key(ssid->wep_key[3],
   1335 					&ssid->wep_key_len[3], line,
   1336 					value, 3);
   1337 }
   1338 
   1339 
   1340 #ifndef NO_CONFIG_WRITE
   1341 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
   1342 {
   1343 	if (ssid->wep_key_len[idx] == 0)
   1344 		return NULL;
   1345 	return wpa_config_write_string(ssid->wep_key[idx],
   1346 				       ssid->wep_key_len[idx]);
   1347 }
   1348 
   1349 
   1350 static char * wpa_config_write_wep_key0(const struct parse_data *data,
   1351 					struct wpa_ssid *ssid)
   1352 {
   1353 	return wpa_config_write_wep_key(ssid, 0);
   1354 }
   1355 
   1356 
   1357 static char * wpa_config_write_wep_key1(const struct parse_data *data,
   1358 					struct wpa_ssid *ssid)
   1359 {
   1360 	return wpa_config_write_wep_key(ssid, 1);
   1361 }
   1362 
   1363 
   1364 static char * wpa_config_write_wep_key2(const struct parse_data *data,
   1365 					struct wpa_ssid *ssid)
   1366 {
   1367 	return wpa_config_write_wep_key(ssid, 2);
   1368 }
   1369 
   1370 
   1371 static char * wpa_config_write_wep_key3(const struct parse_data *data,
   1372 					struct wpa_ssid *ssid)
   1373 {
   1374 	return wpa_config_write_wep_key(ssid, 3);
   1375 }
   1376 #endif /* NO_CONFIG_WRITE */
   1377 
   1378 
   1379 #ifdef CONFIG_P2P
   1380 
   1381 static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
   1382 					    struct wpa_ssid *ssid, int line,
   1383 					    const char *value)
   1384 {
   1385 	const char *pos;
   1386 	u8 *buf, *n, addr[ETH_ALEN];
   1387 	size_t count;
   1388 
   1389 	buf = NULL;
   1390 	count = 0;
   1391 
   1392 	pos = value;
   1393 	while (pos && *pos) {
   1394 		while (*pos == ' ')
   1395 			pos++;
   1396 
   1397 		if (hwaddr_aton(pos, addr)) {
   1398 			if (count == 0) {
   1399 				wpa_printf(MSG_ERROR, "Line %d: Invalid "
   1400 					   "p2p_client_list address '%s'.",
   1401 					   line, value);
   1402 				os_free(buf);
   1403 				return -1;
   1404 			}
   1405 			/* continue anyway since this could have been from a
   1406 			 * truncated configuration file line */
   1407 			wpa_printf(MSG_INFO, "Line %d: Ignore likely "
   1408 				   "truncated p2p_client_list address '%s'",
   1409 				   line, pos);
   1410 		} else {
   1411 			n = os_realloc_array(buf, count + 1, ETH_ALEN);
   1412 			if (n == NULL) {
   1413 				os_free(buf);
   1414 				return -1;
   1415 			}
   1416 			buf = n;
   1417 			os_memmove(buf + ETH_ALEN, buf, count * ETH_ALEN);
   1418 			os_memcpy(buf, addr, ETH_ALEN);
   1419 			count++;
   1420 			wpa_hexdump(MSG_MSGDUMP, "p2p_client_list",
   1421 				    addr, ETH_ALEN);
   1422 		}
   1423 
   1424 		pos = os_strchr(pos, ' ');
   1425 	}
   1426 
   1427 	os_free(ssid->p2p_client_list);
   1428 	ssid->p2p_client_list = buf;
   1429 	ssid->num_p2p_clients = count;
   1430 
   1431 	return 0;
   1432 }
   1433 
   1434 
   1435 #ifndef NO_CONFIG_WRITE
   1436 static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
   1437 					       struct wpa_ssid *ssid)
   1438 {
   1439 	char *value, *end, *pos;
   1440 	int res;
   1441 	size_t i;
   1442 
   1443 	if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0)
   1444 		return NULL;
   1445 
   1446 	value = os_malloc(20 * ssid->num_p2p_clients);
   1447 	if (value == NULL)
   1448 		return NULL;
   1449 	pos = value;
   1450 	end = value + 20 * ssid->num_p2p_clients;
   1451 
   1452 	for (i = ssid->num_p2p_clients; i > 0; i--) {
   1453 		res = os_snprintf(pos, end - pos, MACSTR " ",
   1454 				  MAC2STR(ssid->p2p_client_list +
   1455 					  (i - 1) * ETH_ALEN));
   1456 		if (res < 0 || res >= end - pos) {
   1457 			os_free(value);
   1458 			return NULL;
   1459 		}
   1460 		pos += res;
   1461 	}
   1462 
   1463 	if (pos > value)
   1464 		pos[-1] = '\0';
   1465 
   1466 	return value;
   1467 }
   1468 #endif /* NO_CONFIG_WRITE */
   1469 
   1470 #endif /* CONFIG_P2P */
   1471 
   1472 /* Helper macros for network block parser */
   1473 
   1474 #ifdef OFFSET
   1475 #undef OFFSET
   1476 #endif /* OFFSET */
   1477 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
   1478 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
   1479 
   1480 /* STR: Define a string variable for an ASCII string; f = field name */
   1481 #ifdef NO_CONFIG_WRITE
   1482 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
   1483 #define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
   1484 #else /* NO_CONFIG_WRITE */
   1485 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
   1486 #define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
   1487 #endif /* NO_CONFIG_WRITE */
   1488 #define STR(f) _STR(f), NULL, NULL, NULL, 0
   1489 #define STRe(f) _STRe(f), NULL, NULL, NULL, 0
   1490 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
   1491 #define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
   1492 
   1493 /* STR_LEN: Define a string variable with a separate variable for storing the
   1494  * data length. Unlike STR(), this can be used to store arbitrary binary data
   1495  * (i.e., even nul termination character). */
   1496 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
   1497 #define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
   1498 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
   1499 #define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
   1500 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
   1501 
   1502 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
   1503  * explicitly specified. */
   1504 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
   1505 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
   1506 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
   1507 
   1508 #ifdef NO_CONFIG_WRITE
   1509 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
   1510 #define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
   1511 #else /* NO_CONFIG_WRITE */
   1512 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
   1513 	OFFSET(f), (void *) 0
   1514 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
   1515 	OFFSET(eap.f), (void *) 0
   1516 #endif /* NO_CONFIG_WRITE */
   1517 
   1518 /* INT: Define an integer variable */
   1519 #define INT(f) _INT(f), NULL, NULL, 0
   1520 #define INTe(f) _INTe(f), NULL, NULL, 0
   1521 
   1522 /* INT_RANGE: Define an integer variable with allowed value range */
   1523 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
   1524 
   1525 /* FUNC: Define a configuration variable that uses a custom function for
   1526  * parsing and writing the value. */
   1527 #ifdef NO_CONFIG_WRITE
   1528 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
   1529 #else /* NO_CONFIG_WRITE */
   1530 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
   1531 	NULL, NULL, NULL, NULL
   1532 #endif /* NO_CONFIG_WRITE */
   1533 #define FUNC(f) _FUNC(f), 0
   1534 #define FUNC_KEY(f) _FUNC(f), 1
   1535 
   1536 /*
   1537  * Table of network configuration variables. This table is used to parse each
   1538  * network configuration variable, e.g., each line in wpa_supplicant.conf file
   1539  * that is inside a network block.
   1540  *
   1541  * This table is generated using the helper macros defined above and with
   1542  * generous help from the C pre-processor. The field name is stored as a string
   1543  * into .name and for STR and INT types, the offset of the target buffer within
   1544  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
   1545  * offset to the field containing the length of the configuration variable.
   1546  * .param3 and .param4 can be used to mark the allowed range (length for STR
   1547  * and value for INT).
   1548  *
   1549  * For each configuration line in wpa_supplicant.conf, the parser goes through
   1550  * this table and select the entry that matches with the field name. The parser
   1551  * function (.parser) is then called to parse the actual value of the field.
   1552  *
   1553  * This kind of mechanism makes it easy to add new configuration parameters,
   1554  * since only one line needs to be added into this table and into the
   1555  * struct wpa_ssid definition if the new variable is either a string or
   1556  * integer. More complex types will need to use their own parser and writer
   1557  * functions.
   1558  */
   1559 static const struct parse_data ssid_fields[] = {
   1560 	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
   1561 	{ INT_RANGE(scan_ssid, 0, 1) },
   1562 	{ FUNC(bssid) },
   1563 	{ FUNC_KEY(psk) },
   1564 	{ FUNC(proto) },
   1565 	{ FUNC(key_mgmt) },
   1566 	{ INT(bg_scan_period) },
   1567 	{ FUNC(pairwise) },
   1568 	{ FUNC(group) },
   1569 	{ FUNC(auth_alg) },
   1570 	{ FUNC(scan_freq) },
   1571 	{ FUNC(freq_list) },
   1572 #ifdef IEEE8021X_EAPOL
   1573 	{ FUNC(eap) },
   1574 	{ STR_LENe(identity) },
   1575 	{ STR_LENe(anonymous_identity) },
   1576 	{ FUNC_KEY(password) },
   1577 	{ STRe(ca_cert) },
   1578 	{ STRe(ca_path) },
   1579 	{ STRe(client_cert) },
   1580 	{ STRe(private_key) },
   1581 	{ STR_KEYe(private_key_passwd) },
   1582 	{ STRe(dh_file) },
   1583 	{ STRe(subject_match) },
   1584 	{ STRe(altsubject_match) },
   1585 	{ STRe(ca_cert2) },
   1586 	{ STRe(ca_path2) },
   1587 	{ STRe(client_cert2) },
   1588 	{ STRe(private_key2) },
   1589 	{ STR_KEYe(private_key2_passwd) },
   1590 	{ STRe(dh_file2) },
   1591 	{ STRe(subject_match2) },
   1592 	{ STRe(altsubject_match2) },
   1593 	{ STRe(phase1) },
   1594 	{ STRe(phase2) },
   1595 	{ STRe(pcsc) },
   1596 	{ STR_KEYe(pin) },
   1597 	{ STRe(engine_id) },
   1598 	{ STRe(key_id) },
   1599 	{ STRe(cert_id) },
   1600 	{ STRe(ca_cert_id) },
   1601 	{ STR_KEYe(pin2) },
   1602 	{ STRe(engine2_id) },
   1603 	{ STRe(key2_id) },
   1604 	{ STRe(cert2_id) },
   1605 	{ STRe(ca_cert2_id) },
   1606 	{ INTe(engine) },
   1607 	{ INTe(engine2) },
   1608 	{ INT(eapol_flags) },
   1609 #endif /* IEEE8021X_EAPOL */
   1610 	{ FUNC_KEY(wep_key0) },
   1611 	{ FUNC_KEY(wep_key1) },
   1612 	{ FUNC_KEY(wep_key2) },
   1613 	{ FUNC_KEY(wep_key3) },
   1614 	{ INT(wep_tx_keyidx) },
   1615 	{ INT(priority) },
   1616 #ifdef IEEE8021X_EAPOL
   1617 	{ INT(eap_workaround) },
   1618 	{ STRe(pac_file) },
   1619 	{ INTe(fragment_size) },
   1620 #endif /* IEEE8021X_EAPOL */
   1621 	{ INT_RANGE(mode, 0, 4) },
   1622 	{ INT_RANGE(proactive_key_caching, 0, 1) },
   1623 	{ INT_RANGE(disabled, 0, 2) },
   1624 	{ STR(id_str) },
   1625 #ifdef CONFIG_IEEE80211W
   1626 	{ INT_RANGE(ieee80211w, 0, 2) },
   1627 #endif /* CONFIG_IEEE80211W */
   1628 	{ INT_RANGE(peerkey, 0, 1) },
   1629 	{ INT_RANGE(mixed_cell, 0, 1) },
   1630 	{ INT_RANGE(frequency, 0, 65000) },
   1631 	{ INT(wpa_ptk_rekey) },
   1632 	{ STR(bgscan) },
   1633 	{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
   1634 #ifdef CONFIG_P2P
   1635 	{ FUNC(p2p_client_list) },
   1636 #endif /* CONFIG_P2P */
   1637 #ifdef CONFIG_HT_OVERRIDES
   1638 	{ INT_RANGE(disable_ht, 0, 1) },
   1639 	{ INT_RANGE(disable_ht40, -1, 1) },
   1640 	{ INT_RANGE(disable_sgi, 0, 1) },
   1641 	{ INT_RANGE(disable_max_amsdu, -1, 1) },
   1642 	{ INT_RANGE(ampdu_factor, -1, 3) },
   1643 	{ INT_RANGE(ampdu_density, -1, 7) },
   1644 	{ STR(ht_mcs) },
   1645 #endif /* CONFIG_HT_OVERRIDES */
   1646 	{ INT(ap_max_inactivity) },
   1647 	{ INT(dtim_period) },
   1648 };
   1649 
   1650 #undef OFFSET
   1651 #undef _STR
   1652 #undef STR
   1653 #undef STR_KEY
   1654 #undef _STR_LEN
   1655 #undef STR_LEN
   1656 #undef STR_LEN_KEY
   1657 #undef _STR_RANGE
   1658 #undef STR_RANGE
   1659 #undef STR_RANGE_KEY
   1660 #undef _INT
   1661 #undef INT
   1662 #undef INT_RANGE
   1663 #undef _FUNC
   1664 #undef FUNC
   1665 #undef FUNC_KEY
   1666 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
   1667 
   1668 
   1669 /**
   1670  * wpa_config_add_prio_network - Add a network to priority lists
   1671  * @config: Configuration data from wpa_config_read()
   1672  * @ssid: Pointer to the network configuration to be added to the list
   1673  * Returns: 0 on success, -1 on failure
   1674  *
   1675  * This function is used to add a network block to the priority list of
   1676  * networks. This must be called for each network when reading in the full
   1677  * configuration. In addition, this can be used indirectly when updating
   1678  * priorities by calling wpa_config_update_prio_list().
   1679  */
   1680 int wpa_config_add_prio_network(struct wpa_config *config,
   1681 				struct wpa_ssid *ssid)
   1682 {
   1683 	int prio;
   1684 	struct wpa_ssid *prev, **nlist;
   1685 
   1686 	/*
   1687 	 * Add to an existing priority list if one is available for the
   1688 	 * configured priority level for this network.
   1689 	 */
   1690 	for (prio = 0; prio < config->num_prio; prio++) {
   1691 		prev = config->pssid[prio];
   1692 		if (prev->priority == ssid->priority) {
   1693 			while (prev->pnext)
   1694 				prev = prev->pnext;
   1695 			prev->pnext = ssid;
   1696 			return 0;
   1697 		}
   1698 	}
   1699 
   1700 	/* First network for this priority - add a new priority list */
   1701 	nlist = os_realloc_array(config->pssid, config->num_prio + 1,
   1702 				 sizeof(struct wpa_ssid *));
   1703 	if (nlist == NULL)
   1704 		return -1;
   1705 
   1706 	for (prio = 0; prio < config->num_prio; prio++) {
   1707 		if (nlist[prio]->priority < ssid->priority) {
   1708 			os_memmove(&nlist[prio + 1], &nlist[prio],
   1709 				   (config->num_prio - prio) *
   1710 				   sizeof(struct wpa_ssid *));
   1711 			break;
   1712 		}
   1713 	}
   1714 
   1715 	nlist[prio] = ssid;
   1716 	config->num_prio++;
   1717 	config->pssid = nlist;
   1718 
   1719 	return 0;
   1720 }
   1721 
   1722 
   1723 /**
   1724  * wpa_config_update_prio_list - Update network priority list
   1725  * @config: Configuration data from wpa_config_read()
   1726  * Returns: 0 on success, -1 on failure
   1727  *
   1728  * This function is called to update the priority list of networks in the
   1729  * configuration when a network is being added or removed. This is also called
   1730  * if a priority for a network is changed.
   1731  */
   1732 int wpa_config_update_prio_list(struct wpa_config *config)
   1733 {
   1734 	struct wpa_ssid *ssid;
   1735 	int ret = 0;
   1736 
   1737 	os_free(config->pssid);
   1738 	config->pssid = NULL;
   1739 	config->num_prio = 0;
   1740 
   1741 	ssid = config->ssid;
   1742 	while (ssid) {
   1743 		ssid->pnext = NULL;
   1744 		if (wpa_config_add_prio_network(config, ssid) < 0)
   1745 			ret = -1;
   1746 		ssid = ssid->next;
   1747 	}
   1748 
   1749 	return ret;
   1750 }
   1751 
   1752 
   1753 #ifdef IEEE8021X_EAPOL
   1754 static void eap_peer_config_free(struct eap_peer_config *eap)
   1755 {
   1756 	os_free(eap->eap_methods);
   1757 	os_free(eap->identity);
   1758 	os_free(eap->anonymous_identity);
   1759 	os_free(eap->password);
   1760 	os_free(eap->ca_cert);
   1761 	os_free(eap->ca_path);
   1762 	os_free(eap->client_cert);
   1763 	os_free(eap->private_key);
   1764 	os_free(eap->private_key_passwd);
   1765 	os_free(eap->dh_file);
   1766 	os_free(eap->subject_match);
   1767 	os_free(eap->altsubject_match);
   1768 	os_free(eap->ca_cert2);
   1769 	os_free(eap->ca_path2);
   1770 	os_free(eap->client_cert2);
   1771 	os_free(eap->private_key2);
   1772 	os_free(eap->private_key2_passwd);
   1773 	os_free(eap->dh_file2);
   1774 	os_free(eap->subject_match2);
   1775 	os_free(eap->altsubject_match2);
   1776 	os_free(eap->phase1);
   1777 	os_free(eap->phase2);
   1778 	os_free(eap->pcsc);
   1779 	os_free(eap->pin);
   1780 	os_free(eap->engine_id);
   1781 	os_free(eap->key_id);
   1782 	os_free(eap->cert_id);
   1783 	os_free(eap->ca_cert_id);
   1784 	os_free(eap->key2_id);
   1785 	os_free(eap->cert2_id);
   1786 	os_free(eap->ca_cert2_id);
   1787 	os_free(eap->pin2);
   1788 	os_free(eap->engine2_id);
   1789 	os_free(eap->otp);
   1790 	os_free(eap->pending_req_otp);
   1791 	os_free(eap->pac_file);
   1792 	os_free(eap->new_password);
   1793 }
   1794 #endif /* IEEE8021X_EAPOL */
   1795 
   1796 
   1797 /**
   1798  * wpa_config_free_ssid - Free network/ssid configuration data
   1799  * @ssid: Configuration data for the network
   1800  *
   1801  * This function frees all resources allocated for the network configuration
   1802  * data.
   1803  */
   1804 void wpa_config_free_ssid(struct wpa_ssid *ssid)
   1805 {
   1806 	os_free(ssid->ssid);
   1807 	os_free(ssid->passphrase);
   1808 	os_free(ssid->ext_psk);
   1809 #ifdef IEEE8021X_EAPOL
   1810 	eap_peer_config_free(&ssid->eap);
   1811 #endif /* IEEE8021X_EAPOL */
   1812 	os_free(ssid->id_str);
   1813 	os_free(ssid->scan_freq);
   1814 	os_free(ssid->freq_list);
   1815 	os_free(ssid->bgscan);
   1816 	os_free(ssid->p2p_client_list);
   1817 #ifdef CONFIG_HT_OVERRIDES
   1818 	os_free(ssid->ht_mcs);
   1819 #endif /* CONFIG_HT_OVERRIDES */
   1820 	os_free(ssid);
   1821 }
   1822 
   1823 
   1824 void wpa_config_free_cred(struct wpa_cred *cred)
   1825 {
   1826 	os_free(cred->realm);
   1827 	os_free(cred->username);
   1828 	os_free(cred->password);
   1829 	os_free(cred->ca_cert);
   1830 	os_free(cred->client_cert);
   1831 	os_free(cred->private_key);
   1832 	os_free(cred->private_key_passwd);
   1833 	os_free(cred->imsi);
   1834 	os_free(cred->milenage);
   1835 	os_free(cred->domain);
   1836 	os_free(cred->eap_method);
   1837 	os_free(cred->phase1);
   1838 	os_free(cred->phase2);
   1839 	os_free(cred->excluded_ssid);
   1840 	os_free(cred);
   1841 }
   1842 
   1843 
   1844 /**
   1845  * wpa_config_free - Free configuration data
   1846  * @config: Configuration data from wpa_config_read()
   1847  *
   1848  * This function frees all resources allocated for the configuration data by
   1849  * wpa_config_read().
   1850  */
   1851 void wpa_config_free(struct wpa_config *config)
   1852 {
   1853 #ifndef CONFIG_NO_CONFIG_BLOBS
   1854 	struct wpa_config_blob *blob, *prevblob;
   1855 #endif /* CONFIG_NO_CONFIG_BLOBS */
   1856 	struct wpa_ssid *ssid, *prev = NULL;
   1857 	struct wpa_cred *cred, *cprev;
   1858 
   1859 	ssid = config->ssid;
   1860 	while (ssid) {
   1861 		prev = ssid;
   1862 		ssid = ssid->next;
   1863 		wpa_config_free_ssid(prev);
   1864 	}
   1865 
   1866 	cred = config->cred;
   1867 	while (cred) {
   1868 		cprev = cred;
   1869 		cred = cred->next;
   1870 		wpa_config_free_cred(cprev);
   1871 	}
   1872 
   1873 #ifndef CONFIG_NO_CONFIG_BLOBS
   1874 	blob = config->blobs;
   1875 	prevblob = NULL;
   1876 	while (blob) {
   1877 		prevblob = blob;
   1878 		blob = blob->next;
   1879 		wpa_config_free_blob(prevblob);
   1880 	}
   1881 #endif /* CONFIG_NO_CONFIG_BLOBS */
   1882 
   1883 	wpabuf_free(config->wps_vendor_ext_m1);
   1884 	os_free(config->ctrl_interface);
   1885 	os_free(config->ctrl_interface_group);
   1886 	os_free(config->opensc_engine_path);
   1887 	os_free(config->pkcs11_engine_path);
   1888 	os_free(config->pkcs11_module_path);
   1889 	os_free(config->pcsc_reader);
   1890 	os_free(config->pcsc_pin);
   1891 	os_free(config->driver_param);
   1892 	os_free(config->device_name);
   1893 	os_free(config->manufacturer);
   1894 	os_free(config->model_name);
   1895 	os_free(config->model_number);
   1896 	os_free(config->serial_number);
   1897 	os_free(config->config_methods);
   1898 	os_free(config->p2p_ssid_postfix);
   1899 	os_free(config->pssid);
   1900 	os_free(config->p2p_pref_chan);
   1901 	os_free(config->autoscan);
   1902 	wpabuf_free(config->wps_nfc_dh_pubkey);
   1903 	wpabuf_free(config->wps_nfc_dh_privkey);
   1904 	wpabuf_free(config->wps_nfc_dev_pw);
   1905 	os_free(config->ext_password_backend);
   1906 	os_free(config);
   1907 }
   1908 
   1909 
   1910 /**
   1911  * wpa_config_foreach_network - Iterate over each configured network
   1912  * @config: Configuration data from wpa_config_read()
   1913  * @func: Callback function to process each network
   1914  * @arg: Opaque argument to pass to callback function
   1915  *
   1916  * Iterate over the set of configured networks calling the specified
   1917  * function for each item. We guard against callbacks removing the
   1918  * supplied network.
   1919  */
   1920 void wpa_config_foreach_network(struct wpa_config *config,
   1921 				void (*func)(void *, struct wpa_ssid *),
   1922 				void *arg)
   1923 {
   1924 	struct wpa_ssid *ssid, *next;
   1925 
   1926 	ssid = config->ssid;
   1927 	while (ssid) {
   1928 		next = ssid->next;
   1929 		func(arg, ssid);
   1930 		ssid = next;
   1931 	}
   1932 }
   1933 
   1934 
   1935 /**
   1936  * wpa_config_get_network - Get configured network based on id
   1937  * @config: Configuration data from wpa_config_read()
   1938  * @id: Unique network id to search for
   1939  * Returns: Network configuration or %NULL if not found
   1940  */
   1941 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
   1942 {
   1943 	struct wpa_ssid *ssid;
   1944 
   1945 	ssid = config->ssid;
   1946 	while (ssid) {
   1947 		if (id == ssid->id)
   1948 			break;
   1949 		ssid = ssid->next;
   1950 	}
   1951 
   1952 	return ssid;
   1953 }
   1954 
   1955 
   1956 /**
   1957  * wpa_config_add_network - Add a new network with empty configuration
   1958  * @config: Configuration data from wpa_config_read()
   1959  * Returns: The new network configuration or %NULL if operation failed
   1960  */
   1961 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
   1962 {
   1963 	int id;
   1964 	struct wpa_ssid *ssid, *last = NULL;
   1965 
   1966 	id = -1;
   1967 	ssid = config->ssid;
   1968 	while (ssid) {
   1969 		if (ssid->id > id)
   1970 			id = ssid->id;
   1971 		last = ssid;
   1972 		ssid = ssid->next;
   1973 	}
   1974 	id++;
   1975 
   1976 	ssid = os_zalloc(sizeof(*ssid));
   1977 	if (ssid == NULL)
   1978 		return NULL;
   1979 	ssid->id = id;
   1980 	if (last)
   1981 		last->next = ssid;
   1982 	else
   1983 		config->ssid = ssid;
   1984 
   1985 	wpa_config_update_prio_list(config);
   1986 
   1987 	return ssid;
   1988 }
   1989 
   1990 
   1991 /**
   1992  * wpa_config_remove_network - Remove a configured network based on id
   1993  * @config: Configuration data from wpa_config_read()
   1994  * @id: Unique network id to search for
   1995  * Returns: 0 on success, or -1 if the network was not found
   1996  */
   1997 int wpa_config_remove_network(struct wpa_config *config, int id)
   1998 {
   1999 	struct wpa_ssid *ssid, *prev = NULL;
   2000 
   2001 	ssid = config->ssid;
   2002 	while (ssid) {
   2003 		if (id == ssid->id)
   2004 			break;
   2005 		prev = ssid;
   2006 		ssid = ssid->next;
   2007 	}
   2008 
   2009 	if (ssid == NULL)
   2010 		return -1;
   2011 
   2012 	if (prev)
   2013 		prev->next = ssid->next;
   2014 	else
   2015 		config->ssid = ssid->next;
   2016 
   2017 	wpa_config_update_prio_list(config);
   2018 	wpa_config_free_ssid(ssid);
   2019 	return 0;
   2020 }
   2021 
   2022 
   2023 /**
   2024  * wpa_config_set_network_defaults - Set network default values
   2025  * @ssid: Pointer to network configuration data
   2026  */
   2027 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
   2028 {
   2029 	ssid->proto = DEFAULT_PROTO;
   2030 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
   2031 	ssid->group_cipher = DEFAULT_GROUP;
   2032 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
   2033 	ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
   2034 #ifdef IEEE8021X_EAPOL
   2035 	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
   2036 	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
   2037 	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
   2038 #endif /* IEEE8021X_EAPOL */
   2039 #ifdef CONFIG_HT_OVERRIDES
   2040 	ssid->disable_ht = DEFAULT_DISABLE_HT;
   2041 	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
   2042 	ssid->disable_sgi = DEFAULT_DISABLE_SGI;
   2043 	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
   2044 	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
   2045 	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
   2046 #endif /* CONFIG_HT_OVERRIDES */
   2047 	ssid->proactive_key_caching = -1;
   2048 #ifdef CONFIG_IEEE80211W
   2049 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
   2050 #endif /* CONFIG_IEEE80211W */
   2051 }
   2052 
   2053 
   2054 /**
   2055  * wpa_config_set - Set a variable in network configuration
   2056  * @ssid: Pointer to network configuration data
   2057  * @var: Variable name, e.g., "ssid"
   2058  * @value: Variable value
   2059  * @line: Line number in configuration file or 0 if not used
   2060  * Returns: 0 on success, -1 on failure
   2061  *
   2062  * This function can be used to set network configuration variables based on
   2063  * both the configuration file and management interface input. The value
   2064  * parameter must be in the same format as the text-based configuration file is
   2065  * using. For example, strings are using double quotation marks.
   2066  */
   2067 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
   2068 		   int line)
   2069 {
   2070 	size_t i;
   2071 	int ret = 0;
   2072 
   2073 	if (ssid == NULL || var == NULL || value == NULL)
   2074 		return -1;
   2075 
   2076 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2077 		const struct parse_data *field = &ssid_fields[i];
   2078 		if (os_strcmp(var, field->name) != 0)
   2079 			continue;
   2080 
   2081 		if (field->parser(field, ssid, line, value)) {
   2082 			if (line) {
   2083 				wpa_printf(MSG_ERROR, "Line %d: failed to "
   2084 					   "parse %s '%s'.", line, var, value);
   2085 			}
   2086 			ret = -1;
   2087 		}
   2088 		break;
   2089 	}
   2090 	if (i == NUM_SSID_FIELDS) {
   2091 		if (line) {
   2092 			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
   2093 				   "'%s'.", line, var);
   2094 		}
   2095 		ret = -1;
   2096 	}
   2097 
   2098 	return ret;
   2099 }
   2100 
   2101 
   2102 int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
   2103 			  const char *value)
   2104 {
   2105 	size_t len;
   2106 	char *buf;
   2107 	int ret;
   2108 
   2109 	len = os_strlen(value);
   2110 	buf = os_malloc(len + 3);
   2111 	if (buf == NULL)
   2112 		return -1;
   2113 	buf[0] = '"';
   2114 	os_memcpy(buf + 1, value, len);
   2115 	buf[len + 1] = '"';
   2116 	buf[len + 2] = '\0';
   2117 	ret = wpa_config_set(ssid, var, buf, 0);
   2118 	os_free(buf);
   2119 	return ret;
   2120 }
   2121 
   2122 
   2123 /**
   2124  * wpa_config_get_all - Get all options from network configuration
   2125  * @ssid: Pointer to network configuration data
   2126  * @get_keys: Determines if keys/passwords will be included in returned list
   2127  *	(if they may be exported)
   2128  * Returns: %NULL terminated list of all set keys and their values in the form
   2129  * of [key1, val1, key2, val2, ... , NULL]
   2130  *
   2131  * This function can be used to get list of all configured network properties.
   2132  * The caller is responsible for freeing the returned list and all its
   2133  * elements.
   2134  */
   2135 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
   2136 {
   2137 	const struct parse_data *field;
   2138 	char *key, *value;
   2139 	size_t i;
   2140 	char **props;
   2141 	int fields_num;
   2142 
   2143 	get_keys = get_keys && ssid->export_keys;
   2144 
   2145 	props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *));
   2146 	if (!props)
   2147 		return NULL;
   2148 
   2149 	fields_num = 0;
   2150 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2151 		field = &ssid_fields[i];
   2152 		if (field->key_data && !get_keys)
   2153 			continue;
   2154 		value = field->writer(field, ssid);
   2155 		if (value == NULL)
   2156 			continue;
   2157 		if (os_strlen(value) == 0) {
   2158 			os_free(value);
   2159 			continue;
   2160 		}
   2161 
   2162 		key = os_strdup(field->name);
   2163 		if (key == NULL) {
   2164 			os_free(value);
   2165 			goto err;
   2166 		}
   2167 
   2168 		props[fields_num * 2] = key;
   2169 		props[fields_num * 2 + 1] = value;
   2170 
   2171 		fields_num++;
   2172 	}
   2173 
   2174 	return props;
   2175 
   2176 err:
   2177 	value = *props;
   2178 	while (value)
   2179 		os_free(value++);
   2180 	os_free(props);
   2181 	return NULL;
   2182 }
   2183 
   2184 
   2185 #ifndef NO_CONFIG_WRITE
   2186 /**
   2187  * wpa_config_get - Get a variable in network configuration
   2188  * @ssid: Pointer to network configuration data
   2189  * @var: Variable name, e.g., "ssid"
   2190  * Returns: Value of the variable or %NULL on failure
   2191  *
   2192  * This function can be used to get network configuration variables. The
   2193  * returned value is a copy of the configuration variable in text format, i.e,.
   2194  * the same format that the text-based configuration file and wpa_config_set()
   2195  * are using for the value. The caller is responsible for freeing the returned
   2196  * value.
   2197  */
   2198 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
   2199 {
   2200 	size_t i;
   2201 
   2202 	if (ssid == NULL || var == NULL)
   2203 		return NULL;
   2204 
   2205 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2206 		const struct parse_data *field = &ssid_fields[i];
   2207 		if (os_strcmp(var, field->name) == 0)
   2208 			return field->writer(field, ssid);
   2209 	}
   2210 
   2211 	return NULL;
   2212 }
   2213 
   2214 
   2215 /**
   2216  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
   2217  * @ssid: Pointer to network configuration data
   2218  * @var: Variable name, e.g., "ssid"
   2219  * Returns: Value of the variable or %NULL on failure
   2220  *
   2221  * This function can be used to get network configuration variable like
   2222  * wpa_config_get(). The only difference is that this functions does not expose
   2223  * key/password material from the configuration. In case a key/password field
   2224  * is requested, the returned value is an empty string or %NULL if the variable
   2225  * is not set or "*" if the variable is set (regardless of its value). The
   2226  * returned value is a copy of the configuration variable in text format, i.e,.
   2227  * the same format that the text-based configuration file and wpa_config_set()
   2228  * are using for the value. The caller is responsible for freeing the returned
   2229  * value.
   2230  */
   2231 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
   2232 {
   2233 	size_t i;
   2234 
   2235 	if (ssid == NULL || var == NULL)
   2236 		return NULL;
   2237 
   2238 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   2239 		const struct parse_data *field = &ssid_fields[i];
   2240 		if (os_strcmp(var, field->name) == 0) {
   2241 			char *res = field->writer(field, ssid);
   2242 			if (field->key_data) {
   2243 				if (res && res[0]) {
   2244 					wpa_printf(MSG_DEBUG, "Do not allow "
   2245 						   "key_data field to be "
   2246 						   "exposed");
   2247 					os_free(res);
   2248 					return os_strdup("*");
   2249 				}
   2250 
   2251 				os_free(res);
   2252 				return NULL;
   2253 			}
   2254 			return res;
   2255 		}
   2256 	}
   2257 
   2258 	return NULL;
   2259 }
   2260 #endif /* NO_CONFIG_WRITE */
   2261 
   2262 
   2263 /**
   2264  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
   2265  * @ssid: Pointer to network configuration data
   2266  *
   2267  * This function must be called to update WPA PSK when either SSID or the
   2268  * passphrase has changed for the network configuration.
   2269  */
   2270 void wpa_config_update_psk(struct wpa_ssid *ssid)
   2271 {
   2272 #ifndef CONFIG_NO_PBKDF2
   2273 	pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096,
   2274 		    ssid->psk, PMK_LEN);
   2275 	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
   2276 			ssid->psk, PMK_LEN);
   2277 	ssid->psk_set = 1;
   2278 #endif /* CONFIG_NO_PBKDF2 */
   2279 }
   2280 
   2281 
   2282 int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
   2283 			const char *value, int line)
   2284 {
   2285 	char *val;
   2286 	size_t len;
   2287 
   2288 	if (os_strcmp(var, "priority") == 0) {
   2289 		cred->priority = atoi(value);
   2290 		return 0;
   2291 	}
   2292 
   2293 	if (os_strcmp(var, "pcsc") == 0) {
   2294 		cred->pcsc = atoi(value);
   2295 		return 0;
   2296 	}
   2297 
   2298 	if (os_strcmp(var, "eap") == 0) {
   2299 		struct eap_method_type method;
   2300 		method.method = eap_peer_get_type(value, &method.vendor);
   2301 		if (method.vendor == EAP_VENDOR_IETF &&
   2302 		    method.method == EAP_TYPE_NONE) {
   2303 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' "
   2304 				   "for a credential", line, value);
   2305 			return -1;
   2306 		}
   2307 		os_free(cred->eap_method);
   2308 		cred->eap_method = os_malloc(sizeof(*cred->eap_method));
   2309 		if (cred->eap_method == NULL)
   2310 			return -1;
   2311 		os_memcpy(cred->eap_method, &method, sizeof(method));
   2312 		return 0;
   2313 	}
   2314 
   2315 	if (os_strcmp(var, "password") == 0 &&
   2316 	    os_strncmp(value, "ext:", 4) == 0) {
   2317 		os_free(cred->password);
   2318 		cred->password = os_strdup(value);
   2319 		cred->ext_password = 1;
   2320 		return 0;
   2321 	}
   2322 
   2323 	val = wpa_config_parse_string(value, &len);
   2324 	if (val == NULL) {
   2325 		wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
   2326 			   "value '%s'.", line, var, value);
   2327 		return -1;
   2328 	}
   2329 
   2330 	if (os_strcmp(var, "realm") == 0) {
   2331 		os_free(cred->realm);
   2332 		cred->realm = val;
   2333 		return 0;
   2334 	}
   2335 
   2336 	if (os_strcmp(var, "username") == 0) {
   2337 		os_free(cred->username);
   2338 		cred->username = val;
   2339 		return 0;
   2340 	}
   2341 
   2342 	if (os_strcmp(var, "password") == 0) {
   2343 		os_free(cred->password);
   2344 		cred->password = val;
   2345 		cred->ext_password = 0;
   2346 		return 0;
   2347 	}
   2348 
   2349 	if (os_strcmp(var, "ca_cert") == 0) {
   2350 		os_free(cred->ca_cert);
   2351 		cred->ca_cert = val;
   2352 		return 0;
   2353 	}
   2354 
   2355 	if (os_strcmp(var, "client_cert") == 0) {
   2356 		os_free(cred->client_cert);
   2357 		cred->client_cert = val;
   2358 		return 0;
   2359 	}
   2360 
   2361 	if (os_strcmp(var, "private_key") == 0) {
   2362 		os_free(cred->private_key);
   2363 		cred->private_key = val;
   2364 		return 0;
   2365 	}
   2366 
   2367 	if (os_strcmp(var, "private_key_passwd") == 0) {
   2368 		os_free(cred->private_key_passwd);
   2369 		cred->private_key_passwd = val;
   2370 		return 0;
   2371 	}
   2372 
   2373 	if (os_strcmp(var, "imsi") == 0) {
   2374 		os_free(cred->imsi);
   2375 		cred->imsi = val;
   2376 		return 0;
   2377 	}
   2378 
   2379 	if (os_strcmp(var, "milenage") == 0) {
   2380 		os_free(cred->milenage);
   2381 		cred->milenage = val;
   2382 		return 0;
   2383 	}
   2384 
   2385 	if (os_strcmp(var, "domain") == 0) {
   2386 		os_free(cred->domain);
   2387 		cred->domain = val;
   2388 		return 0;
   2389 	}
   2390 
   2391 	if (os_strcmp(var, "phase1") == 0) {
   2392 		os_free(cred->phase1);
   2393 		cred->phase1 = val;
   2394 		return 0;
   2395 	}
   2396 
   2397 	if (os_strcmp(var, "phase2") == 0) {
   2398 		os_free(cred->phase2);
   2399 		cred->phase2 = val;
   2400 		return 0;
   2401 	}
   2402 
   2403 	if (os_strcmp(var, "roaming_consortium") == 0) {
   2404 		if (len < 3 || len > sizeof(cred->roaming_consortium)) {
   2405 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   2406 				   "roaming_consortium length %d (3..15 "
   2407 				   "expected)", line, (int) len);
   2408 			os_free(val);
   2409 			return -1;
   2410 		}
   2411 		os_memcpy(cred->roaming_consortium, val, len);
   2412 		cred->roaming_consortium_len = len;
   2413 		os_free(val);
   2414 		return 0;
   2415 	}
   2416 
   2417 	if (os_strcmp(var, "excluded_ssid") == 0) {
   2418 		struct excluded_ssid *e;
   2419 
   2420 		if (len > MAX_SSID_LEN) {
   2421 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   2422 				   "excluded_ssid length %d", line, (int) len);
   2423 			os_free(val);
   2424 			return -1;
   2425 		}
   2426 
   2427 		e = os_realloc_array(cred->excluded_ssid,
   2428 				     cred->num_excluded_ssid + 1,
   2429 				     sizeof(struct excluded_ssid));
   2430 		if (e == NULL) {
   2431 			os_free(val);
   2432 			return -1;
   2433 		}
   2434 		cred->excluded_ssid = e;
   2435 
   2436 		e = &cred->excluded_ssid[cred->num_excluded_ssid++];
   2437 		os_memcpy(e->ssid, val, len);
   2438 		e->ssid_len = len;
   2439 
   2440 		os_free(val);
   2441 
   2442 		return 0;
   2443 	}
   2444 
   2445 	if (line) {
   2446 		wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
   2447 			   line, var);
   2448 	}
   2449 
   2450 	os_free(val);
   2451 
   2452 	return -1;
   2453 }
   2454 
   2455 
   2456 struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
   2457 {
   2458 	struct wpa_cred *cred;
   2459 
   2460 	cred = config->cred;
   2461 	while (cred) {
   2462 		if (id == cred->id)
   2463 			break;
   2464 		cred = cred->next;
   2465 	}
   2466 
   2467 	return cred;
   2468 }
   2469 
   2470 
   2471 struct wpa_cred * wpa_config_add_cred(struct wpa_config *config)
   2472 {
   2473 	int id;
   2474 	struct wpa_cred *cred, *last = NULL;
   2475 
   2476 	id = -1;
   2477 	cred = config->cred;
   2478 	while (cred) {
   2479 		if (cred->id > id)
   2480 			id = cred->id;
   2481 		last = cred;
   2482 		cred = cred->next;
   2483 	}
   2484 	id++;
   2485 
   2486 	cred = os_zalloc(sizeof(*cred));
   2487 	if (cred == NULL)
   2488 		return NULL;
   2489 	cred->id = id;
   2490 	if (last)
   2491 		last->next = cred;
   2492 	else
   2493 		config->cred = cred;
   2494 
   2495 	return cred;
   2496 }
   2497 
   2498 
   2499 int wpa_config_remove_cred(struct wpa_config *config, int id)
   2500 {
   2501 	struct wpa_cred *cred, *prev = NULL;
   2502 
   2503 	cred = config->cred;
   2504 	while (cred) {
   2505 		if (id == cred->id)
   2506 			break;
   2507 		prev = cred;
   2508 		cred = cred->next;
   2509 	}
   2510 
   2511 	if (cred == NULL)
   2512 		return -1;
   2513 
   2514 	if (prev)
   2515 		prev->next = cred->next;
   2516 	else
   2517 		config->cred = cred->next;
   2518 
   2519 	wpa_config_free_cred(cred);
   2520 	return 0;
   2521 }
   2522 
   2523 
   2524 #ifndef CONFIG_NO_CONFIG_BLOBS
   2525 /**
   2526  * wpa_config_get_blob - Get a named configuration blob
   2527  * @config: Configuration data from wpa_config_read()
   2528  * @name: Name of the blob
   2529  * Returns: Pointer to blob data or %NULL if not found
   2530  */
   2531 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
   2532 						   const char *name)
   2533 {
   2534 	struct wpa_config_blob *blob = config->blobs;
   2535 
   2536 	while (blob) {
   2537 		if (os_strcmp(blob->name, name) == 0)
   2538 			return blob;
   2539 		blob = blob->next;
   2540 	}
   2541 	return NULL;
   2542 }
   2543 
   2544 
   2545 /**
   2546  * wpa_config_set_blob - Set or add a named configuration blob
   2547  * @config: Configuration data from wpa_config_read()
   2548  * @blob: New value for the blob
   2549  *
   2550  * Adds a new configuration blob or replaces the current value of an existing
   2551  * blob.
   2552  */
   2553 void wpa_config_set_blob(struct wpa_config *config,
   2554 			 struct wpa_config_blob *blob)
   2555 {
   2556 	wpa_config_remove_blob(config, blob->name);
   2557 	blob->next = config->blobs;
   2558 	config->blobs = blob;
   2559 }
   2560 
   2561 
   2562 /**
   2563  * wpa_config_free_blob - Free blob data
   2564  * @blob: Pointer to blob to be freed
   2565  */
   2566 void wpa_config_free_blob(struct wpa_config_blob *blob)
   2567 {
   2568 	if (blob) {
   2569 		os_free(blob->name);
   2570 		os_free(blob->data);
   2571 		os_free(blob);
   2572 	}
   2573 }
   2574 
   2575 
   2576 /**
   2577  * wpa_config_remove_blob - Remove a named configuration blob
   2578  * @config: Configuration data from wpa_config_read()
   2579  * @name: Name of the blob to remove
   2580  * Returns: 0 if blob was removed or -1 if blob was not found
   2581  */
   2582 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
   2583 {
   2584 	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
   2585 
   2586 	while (pos) {
   2587 		if (os_strcmp(pos->name, name) == 0) {
   2588 			if (prev)
   2589 				prev->next = pos->next;
   2590 			else
   2591 				config->blobs = pos->next;
   2592 			wpa_config_free_blob(pos);
   2593 			return 0;
   2594 		}
   2595 		prev = pos;
   2596 		pos = pos->next;
   2597 	}
   2598 
   2599 	return -1;
   2600 }
   2601 #endif /* CONFIG_NO_CONFIG_BLOBS */
   2602 
   2603 
   2604 /**
   2605  * wpa_config_alloc_empty - Allocate an empty configuration
   2606  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
   2607  * socket
   2608  * @driver_param: Driver parameters
   2609  * Returns: Pointer to allocated configuration data or %NULL on failure
   2610  */
   2611 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
   2612 					   const char *driver_param)
   2613 {
   2614 	struct wpa_config *config;
   2615 	const int aCWmin = 4, aCWmax = 10;
   2616 	const struct hostapd_wmm_ac_params ac_bk =
   2617 		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
   2618 	const struct hostapd_wmm_ac_params ac_be =
   2619 		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
   2620 	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
   2621 		{ aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
   2622 	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
   2623 		{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
   2624 
   2625 	config = os_zalloc(sizeof(*config));
   2626 	if (config == NULL)
   2627 		return NULL;
   2628 	config->eapol_version = DEFAULT_EAPOL_VERSION;
   2629 	config->ap_scan = DEFAULT_AP_SCAN;
   2630 	config->fast_reauth = DEFAULT_FAST_REAUTH;
   2631 	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
   2632 	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
   2633 	config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
   2634 	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
   2635 	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
   2636 	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
   2637 	config->max_num_sta = DEFAULT_MAX_NUM_STA;
   2638 	config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
   2639 	config->wmm_ac_params[0] = ac_be;
   2640 	config->wmm_ac_params[1] = ac_bk;
   2641 	config->wmm_ac_params[2] = ac_vi;
   2642 	config->wmm_ac_params[3] = ac_vo;
   2643 
   2644 	if (ctrl_interface)
   2645 		config->ctrl_interface = os_strdup(ctrl_interface);
   2646 	if (driver_param)
   2647 		config->driver_param = os_strdup(driver_param);
   2648 
   2649 	return config;
   2650 }
   2651 
   2652 
   2653 #ifndef CONFIG_NO_STDOUT_DEBUG
   2654 /**
   2655  * wpa_config_debug_dump_networks - Debug dump of configured networks
   2656  * @config: Configuration data from wpa_config_read()
   2657  */
   2658 void wpa_config_debug_dump_networks(struct wpa_config *config)
   2659 {
   2660 	int prio;
   2661 	struct wpa_ssid *ssid;
   2662 
   2663 	for (prio = 0; prio < config->num_prio; prio++) {
   2664 		ssid = config->pssid[prio];
   2665 		wpa_printf(MSG_DEBUG, "Priority group %d",
   2666 			   ssid->priority);
   2667 		while (ssid) {
   2668 			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
   2669 				   ssid->id,
   2670 				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
   2671 			ssid = ssid->pnext;
   2672 		}
   2673 	}
   2674 }
   2675 #endif /* CONFIG_NO_STDOUT_DEBUG */
   2676 
   2677 
   2678 struct global_parse_data {
   2679 	char *name;
   2680 	int (*parser)(const struct global_parse_data *data,
   2681 		      struct wpa_config *config, int line, const char *value);
   2682 	void *param1, *param2, *param3;
   2683 	unsigned int changed_flag;
   2684 };
   2685 
   2686 
   2687 static int wpa_global_config_parse_int(const struct global_parse_data *data,
   2688 				       struct wpa_config *config, int line,
   2689 				       const char *pos)
   2690 {
   2691 	int *dst;
   2692 	dst = (int *) (((u8 *) config) + (long) data->param1);
   2693 	*dst = atoi(pos);
   2694 	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
   2695 
   2696 	if (data->param2 && *dst < (long) data->param2) {
   2697 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
   2698 			   "min_value=%ld)", line, data->name, *dst,
   2699 			   (long) data->param2);
   2700 		*dst = (long) data->param2;
   2701 		return -1;
   2702 	}
   2703 
   2704 	if (data->param3 && *dst > (long) data->param3) {
   2705 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
   2706 			   "max_value=%ld)", line, data->name, *dst,
   2707 			   (long) data->param3);
   2708 		*dst = (long) data->param3;
   2709 		return -1;
   2710 	}
   2711 
   2712 	return 0;
   2713 }
   2714 
   2715 
   2716 static int wpa_global_config_parse_str(const struct global_parse_data *data,
   2717 				       struct wpa_config *config, int line,
   2718 				       const char *pos)
   2719 {
   2720 	size_t len;
   2721 	char **dst, *tmp;
   2722 
   2723 	len = os_strlen(pos);
   2724 	if (data->param2 && len < (size_t) data->param2) {
   2725 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
   2726 			   "min_len=%ld)", line, data->name,
   2727 			   (unsigned long) len, (long) data->param2);
   2728 		return -1;
   2729 	}
   2730 
   2731 	if (data->param3 && len > (size_t) data->param3) {
   2732 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
   2733 			   "max_len=%ld)", line, data->name,
   2734 			   (unsigned long) len, (long) data->param3);
   2735 		return -1;
   2736 	}
   2737 
   2738 	tmp = os_strdup(pos);
   2739 	if (tmp == NULL)
   2740 		return -1;
   2741 
   2742 	dst = (char **) (((u8 *) config) + (long) data->param1);
   2743 	os_free(*dst);
   2744 	*dst = tmp;
   2745 	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
   2746 
   2747 	return 0;
   2748 }
   2749 
   2750 
   2751 static int wpa_global_config_parse_bin(const struct global_parse_data *data,
   2752 				       struct wpa_config *config, int line,
   2753 				       const char *pos)
   2754 {
   2755 	size_t len;
   2756 	struct wpabuf **dst, *tmp;
   2757 
   2758 	len = os_strlen(pos);
   2759 	if (len & 0x01)
   2760 		return -1;
   2761 
   2762 	tmp = wpabuf_alloc(len / 2);
   2763 	if (tmp == NULL)
   2764 		return -1;
   2765 
   2766 	if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) {
   2767 		wpabuf_free(tmp);
   2768 		return -1;
   2769 	}
   2770 
   2771 	dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
   2772 	wpabuf_free(*dst);
   2773 	*dst = tmp;
   2774 	wpa_printf(MSG_DEBUG, "%s", data->name);
   2775 
   2776 	return 0;
   2777 }
   2778 
   2779 
   2780 static int wpa_config_process_country(const struct global_parse_data *data,
   2781 				      struct wpa_config *config, int line,
   2782 				      const char *pos)
   2783 {
   2784 	if (!pos[0] || !pos[1]) {
   2785 		wpa_printf(MSG_DEBUG, "Invalid country set");
   2786 		return -1;
   2787 	}
   2788 	config->country[0] = pos[0];
   2789 	config->country[1] = pos[1];
   2790 	wpa_printf(MSG_DEBUG, "country='%c%c'",
   2791 		   config->country[0], config->country[1]);
   2792 	return 0;
   2793 }
   2794 
   2795 
   2796 static int wpa_config_process_load_dynamic_eap(
   2797 	const struct global_parse_data *data, struct wpa_config *config,
   2798 	int line, const char *so)
   2799 {
   2800 	int ret;
   2801 	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
   2802 	ret = eap_peer_method_load(so);
   2803 	if (ret == -2) {
   2804 		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
   2805 			   "reloading.");
   2806 	} else if (ret) {
   2807 		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
   2808 			   "method '%s'.", line, so);
   2809 		return -1;
   2810 	}
   2811 
   2812 	return 0;
   2813 }
   2814 
   2815 
   2816 #ifdef CONFIG_WPS
   2817 
   2818 static int wpa_config_process_uuid(const struct global_parse_data *data,
   2819 				   struct wpa_config *config, int line,
   2820 				   const char *pos)
   2821 {
   2822 	char buf[40];
   2823 	if (uuid_str2bin(pos, config->uuid)) {
   2824 		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
   2825 		return -1;
   2826 	}
   2827 	uuid_bin2str(config->uuid, buf, sizeof(buf));
   2828 	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
   2829 	return 0;
   2830 }
   2831 
   2832 
   2833 static int wpa_config_process_device_type(
   2834 	const struct global_parse_data *data,
   2835 	struct wpa_config *config, int line, const char *pos)
   2836 {
   2837 	return wps_dev_type_str2bin(pos, config->device_type);
   2838 }
   2839 
   2840 
   2841 static int wpa_config_process_os_version(const struct global_parse_data *data,
   2842 					 struct wpa_config *config, int line,
   2843 					 const char *pos)
   2844 {
   2845 	if (hexstr2bin(pos, config->os_version, 4)) {
   2846 		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
   2847 		return -1;
   2848 	}
   2849 	wpa_printf(MSG_DEBUG, "os_version=%08x",
   2850 		   WPA_GET_BE32(config->os_version));
   2851 	return 0;
   2852 }
   2853 
   2854 
   2855 static int wpa_config_process_wps_vendor_ext_m1(
   2856 	const struct global_parse_data *data,
   2857 	struct wpa_config *config, int line, const char *pos)
   2858 {
   2859 	struct wpabuf *tmp;
   2860 	int len = os_strlen(pos) / 2;
   2861 	u8 *p;
   2862 
   2863 	if (!len) {
   2864 		wpa_printf(MSG_ERROR, "Line %d: "
   2865 			   "invalid wps_vendor_ext_m1", line);
   2866 		return -1;
   2867 	}
   2868 
   2869 	tmp = wpabuf_alloc(len);
   2870 	if (tmp) {
   2871 		p = wpabuf_put(tmp, len);
   2872 
   2873 		if (hexstr2bin(pos, p, len)) {
   2874 			wpa_printf(MSG_ERROR, "Line %d: "
   2875 				   "invalid wps_vendor_ext_m1", line);
   2876 			wpabuf_free(tmp);
   2877 			return -1;
   2878 		}
   2879 
   2880 		wpabuf_free(config->wps_vendor_ext_m1);
   2881 		config->wps_vendor_ext_m1 = tmp;
   2882 	} else {
   2883 		wpa_printf(MSG_ERROR, "Can not allocate "
   2884 			   "memory for wps_vendor_ext_m1");
   2885 		return -1;
   2886 	}
   2887 
   2888 	return 0;
   2889 }
   2890 
   2891 #endif /* CONFIG_WPS */
   2892 
   2893 #ifdef CONFIG_P2P
   2894 static int wpa_config_process_sec_device_type(
   2895 	const struct global_parse_data *data,
   2896 	struct wpa_config *config, int line, const char *pos)
   2897 {
   2898 	int idx;
   2899 
   2900 	if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
   2901 		wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
   2902 			   "items", line);
   2903 		return -1;
   2904 	}
   2905 
   2906 	idx = config->num_sec_device_types;
   2907 
   2908 	if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
   2909 		return -1;
   2910 
   2911 	config->num_sec_device_types++;
   2912 	return 0;
   2913 }
   2914 
   2915 
   2916 static int wpa_config_process_p2p_pref_chan(
   2917 	const struct global_parse_data *data,
   2918 	struct wpa_config *config, int line, const char *pos)
   2919 {
   2920 	struct p2p_channel *pref = NULL, *n;
   2921 	unsigned int num = 0;
   2922 	const char *pos2;
   2923 	u8 op_class, chan;
   2924 
   2925 	/* format: class:chan,class:chan,... */
   2926 
   2927 	while (*pos) {
   2928 		op_class = atoi(pos);
   2929 		pos2 = os_strchr(pos, ':');
   2930 		if (pos2 == NULL)
   2931 			goto fail;
   2932 		pos2++;
   2933 		chan = atoi(pos2);
   2934 
   2935 		n = os_realloc_array(pref, num + 1,
   2936 				     sizeof(struct p2p_channel));
   2937 		if (n == NULL)
   2938 			goto fail;
   2939 		pref = n;
   2940 		pref[num].op_class = op_class;
   2941 		pref[num].chan = chan;
   2942 		num++;
   2943 
   2944 		pos = os_strchr(pos2, ',');
   2945 		if (pos == NULL)
   2946 			break;
   2947 		pos++;
   2948 	}
   2949 
   2950 	os_free(config->p2p_pref_chan);
   2951 	config->p2p_pref_chan = pref;
   2952 	config->num_p2p_pref_chan = num;
   2953 	wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs",
   2954 		    (u8 *) config->p2p_pref_chan,
   2955 		    config->num_p2p_pref_chan * sizeof(struct p2p_channel));
   2956 
   2957 	return 0;
   2958 
   2959 fail:
   2960 	os_free(pref);
   2961 	wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line);
   2962 	return -1;
   2963 }
   2964 #endif /* CONFIG_P2P */
   2965 
   2966 
   2967 static int wpa_config_process_hessid(
   2968 	const struct global_parse_data *data,
   2969 	struct wpa_config *config, int line, const char *pos)
   2970 {
   2971 	if (hwaddr_aton2(pos, config->hessid) < 0) {
   2972 		wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
   2973 			   line, pos);
   2974 		return -1;
   2975 	}
   2976 
   2977 	return 0;
   2978 }
   2979 
   2980 
   2981 #ifdef OFFSET
   2982 #undef OFFSET
   2983 #endif /* OFFSET */
   2984 /* OFFSET: Get offset of a variable within the wpa_config structure */
   2985 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
   2986 
   2987 #define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
   2988 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
   2989 #define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
   2990 #define INT(f) _INT(f), NULL, NULL
   2991 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
   2992 #define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
   2993 #define STR(f) _STR(f), NULL, NULL
   2994 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
   2995 #define BIN(f) #f, wpa_global_config_parse_bin, OFFSET(f), NULL, NULL
   2996 
   2997 static const struct global_parse_data global_fields[] = {
   2998 #ifdef CONFIG_CTRL_IFACE
   2999 	{ STR(ctrl_interface), 0 },
   3000 	{ STR(ctrl_interface_group), 0 } /* deprecated */,
   3001 #endif /* CONFIG_CTRL_IFACE */
   3002 	{ INT_RANGE(eapol_version, 1, 2), 0 },
   3003 	{ INT(ap_scan), 0 },
   3004 	{ INT(disable_scan_offload), 0 },
   3005 	{ INT(fast_reauth), 0 },
   3006 	{ STR(opensc_engine_path), 0 },
   3007 	{ STR(pkcs11_engine_path), 0 },
   3008 	{ STR(pkcs11_module_path), 0 },
   3009 	{ STR(pcsc_reader), 0 },
   3010 	{ STR(pcsc_pin), 0 },
   3011 	{ STR(driver_param), 0 },
   3012 	{ INT(dot11RSNAConfigPMKLifetime), 0 },
   3013 	{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
   3014 	{ INT(dot11RSNAConfigSATimeout), 0 },
   3015 #ifndef CONFIG_NO_CONFIG_WRITE
   3016 	{ INT(update_config), 0 },
   3017 #endif /* CONFIG_NO_CONFIG_WRITE */
   3018 	{ FUNC_NO_VAR(load_dynamic_eap), 0 },
   3019 #ifdef CONFIG_WPS
   3020 	{ FUNC(uuid), CFG_CHANGED_UUID },
   3021 	{ STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
   3022 	{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
   3023 	{ STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
   3024 	{ STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
   3025 	{ STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
   3026 	{ FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
   3027 	{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
   3028 	{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
   3029 	{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
   3030 	{ FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
   3031 #endif /* CONFIG_WPS */
   3032 #ifdef CONFIG_P2P
   3033 	{ FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
   3034 	{ INT(p2p_listen_reg_class), 0 },
   3035 	{ INT(p2p_listen_channel), 0 },
   3036 	{ INT(p2p_oper_reg_class), 0 },
   3037 	{ INT(p2p_oper_channel), 0 },
   3038 	{ INT_RANGE(p2p_go_intent, 0, 15), 0 },
   3039 	{ STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
   3040 	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
   3041 	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
   3042 	{ INT(p2p_group_idle), 0 },
   3043 	{ FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
   3044 	{ INT(p2p_go_ht40), 0 },
   3045 	{ INT(p2p_disabled), 0 },
   3046 	{ INT(p2p_no_group_iface), 0 },
   3047 #endif /* CONFIG_P2P */
   3048 	{ FUNC(country), CFG_CHANGED_COUNTRY },
   3049 	{ INT(bss_max_count), 0 },
   3050 	{ INT(bss_expiration_age), 0 },
   3051 	{ INT(bss_expiration_scan_count), 0 },
   3052 	{ INT_RANGE(filter_ssids, 0, 1), 0 },
   3053 	{ INT_RANGE(filter_rssi, -100, 0), 0 },
   3054 	{ INT(max_num_sta), 0 },
   3055 	{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
   3056 #ifdef CONFIG_HS20
   3057 	{ INT_RANGE(hs20, 0, 1), 0 },
   3058 #endif /* CONFIG_HS20 */
   3059 	{ INT_RANGE(interworking, 0, 1), 0 },
   3060 	{ FUNC(hessid), 0 },
   3061 	{ INT_RANGE(access_network_type, 0, 15), 0 },
   3062 	{ INT_RANGE(pbc_in_m1, 0, 1), 0 },
   3063 	{ STR(autoscan), 0 },
   3064 	{ INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff), 0 },
   3065 	{ BIN(wps_nfc_dh_pubkey), 0 },
   3066 	{ BIN(wps_nfc_dh_privkey), 0 },
   3067 	{ BIN(wps_nfc_dev_pw), 0 },
   3068 	{ STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
   3069 	{ INT(p2p_go_max_inactivity), 0 },
   3070 	{ INT_RANGE(auto_interworking, 0, 1), 0 },
   3071 	{ INT(okc), 0 },
   3072 	{ INT(pmf), 0 },
   3073 };
   3074 
   3075 #undef FUNC
   3076 #undef _INT
   3077 #undef INT
   3078 #undef INT_RANGE
   3079 #undef _STR
   3080 #undef STR
   3081 #undef STR_RANGE
   3082 #undef BIN
   3083 #define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
   3084 
   3085 
   3086 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
   3087 {
   3088 	size_t i;
   3089 	int ret = 0;
   3090 
   3091 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   3092 		const struct global_parse_data *field = &global_fields[i];
   3093 		size_t flen = os_strlen(field->name);
   3094 		if (os_strncmp(pos, field->name, flen) != 0 ||
   3095 		    pos[flen] != '=')
   3096 			continue;
   3097 
   3098 		if (field->parser(field, config, line, pos + flen + 1)) {
   3099 			wpa_printf(MSG_ERROR, "Line %d: failed to "
   3100 				   "parse '%s'.", line, pos);
   3101 			ret = -1;
   3102 		}
   3103 		config->changed_parameters |= field->changed_flag;
   3104 		break;
   3105 	}
   3106 	if (i == NUM_GLOBAL_FIELDS) {
   3107 #ifdef CONFIG_AP
   3108 		if (os_strncmp(pos, "wmm_ac_", 7) == 0) {
   3109 			char *tmp = os_strchr(pos, '=');
   3110 			if (tmp == NULL) {
   3111 				if (line < 0)
   3112 					return -1;
   3113 				wpa_printf(MSG_ERROR, "Line %d: invalid line "
   3114 					   "'%s'", line, pos);
   3115 				return -1;
   3116 			}
   3117 			*tmp++ = '\0';
   3118 			if (hostapd_config_wmm_ac(config->wmm_ac_params, pos,
   3119 						  tmp)) {
   3120 				wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
   3121 					   "AC item", line);
   3122 				return -1;
   3123 			}
   3124 		}
   3125 #endif /* CONFIG_AP */
   3126 		if (line < 0)
   3127 			return -1;
   3128 		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
   3129 			   line, pos);
   3130 		ret = -1;
   3131 	}
   3132 
   3133 	return ret;
   3134 }
   3135