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