Home | History | Annotate | Line # | Download | only in wpa_supplicant
      1  1.1  christos /*
      2  1.1  christos  * WPA Supplicant / Configuration parser and common functions
      3  1.9  christos  * Copyright (c) 2003-2019, Jouni Malinen <j (at) w1.fi>
      4  1.1  christos  *
      5  1.2  christos  * This software may be distributed under the terms of the BSD license.
      6  1.2  christos  * See README for more details.
      7  1.1  christos  */
      8  1.1  christos 
      9  1.1  christos #include "includes.h"
     10  1.1  christos 
     11  1.1  christos #include "common.h"
     12  1.2  christos #include "utils/uuid.h"
     13  1.2  christos #include "utils/ip_addr.h"
     14  1.7  christos #include "common/ieee802_1x_defs.h"
     15  1.9  christos #include "common/sae.h"
     16  1.1  christos #include "crypto/sha1.h"
     17  1.1  christos #include "rsn_supp/wpa.h"
     18  1.1  christos #include "eap_peer/eap.h"
     19  1.2  christos #include "p2p/p2p.h"
     20  1.6  christos #include "fst/fst.h"
     21  1.1  christos #include "config.h"
     22  1.1  christos 
     23  1.1  christos 
     24  1.1  christos #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
     25  1.1  christos #define NO_CONFIG_WRITE
     26  1.1  christos #endif
     27  1.1  christos 
     28  1.1  christos /*
     29  1.1  christos  * Structure for network configuration parsing. This data is used to implement
     30  1.1  christos  * a generic parser for each network block variable. The table of configuration
     31  1.1  christos  * variables is defined below in this file (ssid_fields[]).
     32  1.1  christos  */
     33  1.1  christos struct parse_data {
     34  1.1  christos 	/* Configuration variable name */
     35  1.1  christos 	char *name;
     36  1.1  christos 
     37  1.6  christos 	/* Parser function for this variable. The parser functions return 0 or 1
     38  1.6  christos 	 * to indicate success. Value 0 indicates that the parameter value may
     39  1.6  christos 	 * have changed while value 1 means that the value did not change.
     40  1.6  christos 	 * Error cases (failure to parse the string) are indicated by returning
     41  1.6  christos 	 * -1. */
     42  1.1  christos 	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
     43  1.1  christos 		      int line, const char *value);
     44  1.1  christos 
     45  1.1  christos #ifndef NO_CONFIG_WRITE
     46  1.1  christos 	/* Writer function (i.e., to get the variable in text format from
     47  1.1  christos 	 * internal presentation). */
     48  1.1  christos 	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
     49  1.1  christos #endif /* NO_CONFIG_WRITE */
     50  1.1  christos 
     51  1.1  christos 	/* Variable specific parameters for the parser. */
     52  1.1  christos 	void *param1, *param2, *param3, *param4;
     53  1.1  christos 
     54  1.1  christos 	/* 0 = this variable can be included in debug output and ctrl_iface
     55  1.1  christos 	 * 1 = this variable contains key/private data and it must not be
     56  1.1  christos 	 *     included in debug output unless explicitly requested. In
     57  1.1  christos 	 *     addition, this variable will not be readable through the
     58  1.1  christos 	 *     ctrl_iface.
     59  1.1  christos 	 */
     60  1.1  christos 	int key_data;
     61  1.1  christos };
     62  1.1  christos 
     63  1.1  christos 
     64  1.1  christos static int wpa_config_parse_str(const struct parse_data *data,
     65  1.1  christos 				struct wpa_ssid *ssid,
     66  1.1  christos 				int line, const char *value)
     67  1.1  christos {
     68  1.6  christos 	size_t res_len, *dst_len, prev_len;
     69  1.1  christos 	char **dst, *tmp;
     70  1.1  christos 
     71  1.1  christos 	if (os_strcmp(value, "NULL") == 0) {
     72  1.1  christos 		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
     73  1.1  christos 			   data->name);
     74  1.1  christos 		tmp = NULL;
     75  1.1  christos 		res_len = 0;
     76  1.1  christos 		goto set;
     77  1.1  christos 	}
     78  1.1  christos 
     79  1.1  christos 	tmp = wpa_config_parse_string(value, &res_len);
     80  1.1  christos 	if (tmp == NULL) {
     81  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
     82  1.1  christos 			   line, data->name,
     83  1.1  christos 			   data->key_data ? "[KEY DATA REMOVED]" : value);
     84  1.1  christos 		return -1;
     85  1.1  christos 	}
     86  1.1  christos 
     87  1.1  christos 	if (data->key_data) {
     88  1.1  christos 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
     89  1.1  christos 				      (u8 *) tmp, res_len);
     90  1.1  christos 	} else {
     91  1.1  christos 		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
     92  1.1  christos 				  (u8 *) tmp, res_len);
     93  1.1  christos 	}
     94  1.1  christos 
     95  1.1  christos 	if (data->param3 && res_len < (size_t) data->param3) {
     96  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
     97  1.1  christos 			   "min_len=%ld)", line, data->name,
     98  1.1  christos 			   (unsigned long) res_len, (long) data->param3);
     99  1.1  christos 		os_free(tmp);
    100  1.1  christos 		return -1;
    101  1.1  christos 	}
    102  1.1  christos 
    103  1.1  christos 	if (data->param4 && res_len > (size_t) data->param4) {
    104  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
    105  1.1  christos 			   "max_len=%ld)", line, data->name,
    106  1.1  christos 			   (unsigned long) res_len, (long) data->param4);
    107  1.1  christos 		os_free(tmp);
    108  1.1  christos 		return -1;
    109  1.1  christos 	}
    110  1.1  christos 
    111  1.1  christos set:
    112  1.1  christos 	dst = (char **) (((u8 *) ssid) + (long) data->param1);
    113  1.1  christos 	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
    114  1.6  christos 
    115  1.6  christos 	if (data->param2)
    116  1.6  christos 		prev_len = *dst_len;
    117  1.6  christos 	else if (*dst)
    118  1.6  christos 		prev_len = os_strlen(*dst);
    119  1.6  christos 	else
    120  1.6  christos 		prev_len = 0;
    121  1.6  christos 	if ((*dst == NULL && tmp == NULL) ||
    122  1.6  christos 	    (*dst && tmp && prev_len == res_len &&
    123  1.6  christos 	     os_memcmp(*dst, tmp, res_len) == 0)) {
    124  1.6  christos 		/* No change to the previously configured value */
    125  1.6  christos 		os_free(tmp);
    126  1.6  christos 		return 1;
    127  1.6  christos 	}
    128  1.6  christos 
    129  1.1  christos 	os_free(*dst);
    130  1.1  christos 	*dst = tmp;
    131  1.1  christos 	if (data->param2)
    132  1.1  christos 		*dst_len = res_len;
    133  1.1  christos 
    134  1.1  christos 	return 0;
    135  1.1  christos }
    136  1.1  christos 
    137  1.1  christos 
    138  1.1  christos #ifndef NO_CONFIG_WRITE
    139  1.1  christos static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
    140  1.1  christos {
    141  1.1  christos 	char *buf;
    142  1.1  christos 
    143  1.1  christos 	buf = os_malloc(len + 3);
    144  1.1  christos 	if (buf == NULL)
    145  1.1  christos 		return NULL;
    146  1.1  christos 	buf[0] = '"';
    147  1.1  christos 	os_memcpy(buf + 1, value, len);
    148  1.1  christos 	buf[len + 1] = '"';
    149  1.1  christos 	buf[len + 2] = '\0';
    150  1.1  christos 
    151  1.1  christos 	return buf;
    152  1.1  christos }
    153  1.1  christos 
    154  1.1  christos 
    155  1.1  christos static char * wpa_config_write_string_hex(const u8 *value, size_t len)
    156  1.1  christos {
    157  1.1  christos 	char *buf;
    158  1.1  christos 
    159  1.1  christos 	buf = os_zalloc(2 * len + 1);
    160  1.1  christos 	if (buf == NULL)
    161  1.1  christos 		return NULL;
    162  1.1  christos 	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
    163  1.1  christos 
    164  1.1  christos 	return buf;
    165  1.1  christos }
    166  1.1  christos 
    167  1.1  christos 
    168  1.1  christos static char * wpa_config_write_string(const u8 *value, size_t len)
    169  1.1  christos {
    170  1.1  christos 	if (value == NULL)
    171  1.1  christos 		return NULL;
    172  1.1  christos 
    173  1.1  christos 	if (is_hex(value, len))
    174  1.1  christos 		return wpa_config_write_string_hex(value, len);
    175  1.1  christos 	else
    176  1.1  christos 		return wpa_config_write_string_ascii(value, len);
    177  1.1  christos }
    178  1.1  christos 
    179  1.1  christos 
    180  1.1  christos static char * wpa_config_write_str(const struct parse_data *data,
    181  1.1  christos 				   struct wpa_ssid *ssid)
    182  1.1  christos {
    183  1.1  christos 	size_t len;
    184  1.1  christos 	char **src;
    185  1.1  christos 
    186  1.1  christos 	src = (char **) (((u8 *) ssid) + (long) data->param1);
    187  1.1  christos 	if (*src == NULL)
    188  1.1  christos 		return NULL;
    189  1.1  christos 
    190  1.1  christos 	if (data->param2)
    191  1.1  christos 		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
    192  1.1  christos 	else
    193  1.1  christos 		len = os_strlen(*src);
    194  1.1  christos 
    195  1.1  christos 	return wpa_config_write_string((const u8 *) *src, len);
    196  1.1  christos }
    197  1.1  christos #endif /* NO_CONFIG_WRITE */
    198  1.1  christos 
    199  1.1  christos 
    200  1.9  christos static int wpa_config_parse_int_impl(const struct parse_data *data,
    201  1.9  christos 				     struct wpa_ssid *ssid,
    202  1.9  christos 				     int line, const char *value,
    203  1.9  christos 				     bool check_range)
    204  1.1  christos {
    205  1.2  christos 	int val, *dst;
    206  1.2  christos 	char *end;
    207  1.1  christos 
    208  1.1  christos 	dst = (int *) (((u8 *) ssid) + (long) data->param1);
    209  1.2  christos 	val = strtol(value, &end, 0);
    210  1.2  christos 	if (*end) {
    211  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
    212  1.2  christos 			   line, value);
    213  1.2  christos 		return -1;
    214  1.2  christos 	}
    215  1.6  christos 
    216  1.9  christos 	if (check_range && val < (long) data->param3) {
    217  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
    218  1.9  christos 			   "min_value=%ld)", line, data->name, val,
    219  1.1  christos 			   (long) data->param3);
    220  1.1  christos 		return -1;
    221  1.1  christos 	}
    222  1.1  christos 
    223  1.9  christos 	if (check_range && val > (long) data->param4) {
    224  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
    225  1.9  christos 			   "max_value=%ld)", line, data->name, val,
    226  1.1  christos 			   (long) data->param4);
    227  1.1  christos 		return -1;
    228  1.1  christos 	}
    229  1.1  christos 
    230  1.9  christos 	if (*dst == val)
    231  1.9  christos 		return 1;
    232  1.9  christos 
    233  1.9  christos 	*dst = val;
    234  1.9  christos 	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
    235  1.9  christos 
    236  1.1  christos 	return 0;
    237  1.1  christos }
    238  1.1  christos 
    239  1.1  christos 
    240  1.9  christos static int wpa_config_parse_int(const struct parse_data *data,
    241  1.9  christos 				struct wpa_ssid *ssid,
    242  1.9  christos 				int line, const char *value)
    243  1.9  christos {
    244  1.9  christos 	return wpa_config_parse_int_impl(data, ssid, line, value, false);
    245  1.9  christos }
    246  1.9  christos 
    247  1.9  christos 
    248  1.9  christos static int wpa_config_parse_int_range(const struct parse_data *data,
    249  1.9  christos 				      struct wpa_ssid *ssid,
    250  1.9  christos 				      int line, const char *value)
    251  1.9  christos {
    252  1.9  christos 	return wpa_config_parse_int_impl(data, ssid, line, value, true);
    253  1.9  christos }
    254  1.9  christos 
    255  1.9  christos 
    256  1.1  christos #ifndef NO_CONFIG_WRITE
    257  1.1  christos static char * wpa_config_write_int(const struct parse_data *data,
    258  1.1  christos 				   struct wpa_ssid *ssid)
    259  1.1  christos {
    260  1.1  christos 	int *src, res;
    261  1.1  christos 	char *value;
    262  1.1  christos 
    263  1.1  christos 	src = (int *) (((u8 *) ssid) + (long) data->param1);
    264  1.1  christos 
    265  1.1  christos 	value = os_malloc(20);
    266  1.1  christos 	if (value == NULL)
    267  1.1  christos 		return NULL;
    268  1.1  christos 	res = os_snprintf(value, 20, "%d", *src);
    269  1.2  christos 	if (os_snprintf_error(20, res)) {
    270  1.1  christos 		os_free(value);
    271  1.1  christos 		return NULL;
    272  1.1  christos 	}
    273  1.1  christos 	value[20 - 1] = '\0';
    274  1.1  christos 	return value;
    275  1.1  christos }
    276  1.1  christos #endif /* NO_CONFIG_WRITE */
    277  1.1  christos 
    278  1.1  christos 
    279  1.2  christos static int wpa_config_parse_addr_list(const struct parse_data *data,
    280  1.2  christos 				      int line, const char *value,
    281  1.2  christos 				      u8 **list, size_t *num, char *name,
    282  1.2  christos 				      u8 abort_on_error, u8 masked)
    283  1.2  christos {
    284  1.2  christos 	const char *pos;
    285  1.2  christos 	u8 *buf, *n, addr[2 * ETH_ALEN];
    286  1.2  christos 	size_t count;
    287  1.2  christos 
    288  1.2  christos 	buf = NULL;
    289  1.2  christos 	count = 0;
    290  1.2  christos 
    291  1.2  christos 	pos = value;
    292  1.2  christos 	while (pos && *pos) {
    293  1.2  christos 		while (*pos == ' ')
    294  1.2  christos 			pos++;
    295  1.2  christos 
    296  1.2  christos 		if (hwaddr_masked_aton(pos, addr, &addr[ETH_ALEN], masked)) {
    297  1.2  christos 			if (abort_on_error || count == 0) {
    298  1.2  christos 				wpa_printf(MSG_ERROR,
    299  1.2  christos 					   "Line %d: Invalid %s address '%s'",
    300  1.2  christos 					   line, name, value);
    301  1.2  christos 				os_free(buf);
    302  1.2  christos 				return -1;
    303  1.2  christos 			}
    304  1.2  christos 			/* continue anyway since this could have been from a
    305  1.2  christos 			 * truncated configuration file line */
    306  1.2  christos 			wpa_printf(MSG_INFO,
    307  1.2  christos 				   "Line %d: Ignore likely truncated %s address '%s'",
    308  1.2  christos 				   line, name, pos);
    309  1.2  christos 		} else {
    310  1.2  christos 			n = os_realloc_array(buf, count + 1, 2 * ETH_ALEN);
    311  1.2  christos 			if (n == NULL) {
    312  1.2  christos 				os_free(buf);
    313  1.2  christos 				return -1;
    314  1.2  christos 			}
    315  1.2  christos 			buf = n;
    316  1.2  christos 			os_memmove(buf + 2 * ETH_ALEN, buf,
    317  1.2  christos 				   count * 2 * ETH_ALEN);
    318  1.2  christos 			os_memcpy(buf, addr, 2 * ETH_ALEN);
    319  1.2  christos 			count++;
    320  1.2  christos 			wpa_printf(MSG_MSGDUMP,
    321  1.2  christos 				   "%s: addr=" MACSTR " mask=" MACSTR,
    322  1.2  christos 				   name, MAC2STR(addr),
    323  1.2  christos 				   MAC2STR(&addr[ETH_ALEN]));
    324  1.2  christos 		}
    325  1.2  christos 
    326  1.2  christos 		pos = os_strchr(pos, ' ');
    327  1.2  christos 	}
    328  1.2  christos 
    329  1.2  christos 	os_free(*list);
    330  1.2  christos 	*list = buf;
    331  1.2  christos 	*num = count;
    332  1.2  christos 
    333  1.2  christos 	return 0;
    334  1.2  christos }
    335  1.2  christos 
    336  1.2  christos 
    337  1.2  christos #ifndef NO_CONFIG_WRITE
    338  1.2  christos static char * wpa_config_write_addr_list(const struct parse_data *data,
    339  1.2  christos 					 const u8 *list, size_t num, char *name)
    340  1.2  christos {
    341  1.2  christos 	char *value, *end, *pos;
    342  1.2  christos 	int res;
    343  1.2  christos 	size_t i;
    344  1.2  christos 
    345  1.2  christos 	if (list == NULL || num == 0)
    346  1.2  christos 		return NULL;
    347  1.2  christos 
    348  1.2  christos 	value = os_malloc(2 * 20 * num);
    349  1.2  christos 	if (value == NULL)
    350  1.2  christos 		return NULL;
    351  1.2  christos 	pos = value;
    352  1.2  christos 	end = value + 2 * 20 * num;
    353  1.2  christos 
    354  1.2  christos 	for (i = num; i > 0; i--) {
    355  1.2  christos 		const u8 *a = list + (i - 1) * 2 * ETH_ALEN;
    356  1.2  christos 		const u8 *m = a + ETH_ALEN;
    357  1.2  christos 
    358  1.2  christos 		if (i < num)
    359  1.2  christos 			*pos++ = ' ';
    360  1.2  christos 		res = hwaddr_mask_txt(pos, end - pos, a, m);
    361  1.2  christos 		if (res < 0) {
    362  1.2  christos 			os_free(value);
    363  1.2  christos 			return NULL;
    364  1.2  christos 		}
    365  1.2  christos 		pos += res;
    366  1.2  christos 	}
    367  1.2  christos 
    368  1.2  christos 	return value;
    369  1.2  christos }
    370  1.2  christos #endif /* NO_CONFIG_WRITE */
    371  1.2  christos 
    372  1.1  christos static int wpa_config_parse_bssid(const struct parse_data *data,
    373  1.1  christos 				  struct wpa_ssid *ssid, int line,
    374  1.1  christos 				  const char *value)
    375  1.1  christos {
    376  1.2  christos 	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
    377  1.2  christos 	    os_strcmp(value, "any") == 0) {
    378  1.2  christos 		ssid->bssid_set = 0;
    379  1.2  christos 		wpa_printf(MSG_MSGDUMP, "BSSID any");
    380  1.2  christos 		return 0;
    381  1.2  christos 	}
    382  1.1  christos 	if (hwaddr_aton(value, ssid->bssid)) {
    383  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
    384  1.1  christos 			   line, value);
    385  1.1  christos 		return -1;
    386  1.1  christos 	}
    387  1.1  christos 	ssid->bssid_set = 1;
    388  1.1  christos 	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
    389  1.1  christos 	return 0;
    390  1.1  christos }
    391  1.1  christos 
    392  1.1  christos 
    393  1.1  christos #ifndef NO_CONFIG_WRITE
    394  1.1  christos static char * wpa_config_write_bssid(const struct parse_data *data,
    395  1.1  christos 				     struct wpa_ssid *ssid)
    396  1.1  christos {
    397  1.1  christos 	char *value;
    398  1.1  christos 	int res;
    399  1.1  christos 
    400  1.1  christos 	if (!ssid->bssid_set)
    401  1.1  christos 		return NULL;
    402  1.1  christos 
    403  1.1  christos 	value = os_malloc(20);
    404  1.1  christos 	if (value == NULL)
    405  1.1  christos 		return NULL;
    406  1.1  christos 	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
    407  1.2  christos 	if (os_snprintf_error(20, res)) {
    408  1.1  christos 		os_free(value);
    409  1.1  christos 		return NULL;
    410  1.1  christos 	}
    411  1.1  christos 	value[20 - 1] = '\0';
    412  1.1  christos 	return value;
    413  1.1  christos }
    414  1.1  christos #endif /* NO_CONFIG_WRITE */
    415  1.1  christos 
    416  1.1  christos 
    417  1.7  christos static int wpa_config_parse_bssid_hint(const struct parse_data *data,
    418  1.7  christos 				       struct wpa_ssid *ssid, int line,
    419  1.7  christos 				       const char *value)
    420  1.7  christos {
    421  1.7  christos 	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
    422  1.7  christos 	    os_strcmp(value, "any") == 0) {
    423  1.7  christos 		ssid->bssid_hint_set = 0;
    424  1.7  christos 		wpa_printf(MSG_MSGDUMP, "BSSID hint any");
    425  1.7  christos 		return 0;
    426  1.7  christos 	}
    427  1.7  christos 	if (hwaddr_aton(value, ssid->bssid_hint)) {
    428  1.7  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID hint '%s'.",
    429  1.7  christos 			   line, value);
    430  1.7  christos 		return -1;
    431  1.7  christos 	}
    432  1.7  christos 	ssid->bssid_hint_set = 1;
    433  1.7  christos 	wpa_hexdump(MSG_MSGDUMP, "BSSID hint", ssid->bssid_hint, ETH_ALEN);
    434  1.7  christos 	return 0;
    435  1.7  christos }
    436  1.7  christos 
    437  1.7  christos 
    438  1.7  christos #ifndef NO_CONFIG_WRITE
    439  1.7  christos static char * wpa_config_write_bssid_hint(const struct parse_data *data,
    440  1.7  christos 					  struct wpa_ssid *ssid)
    441  1.7  christos {
    442  1.7  christos 	char *value;
    443  1.7  christos 	int res;
    444  1.7  christos 
    445  1.7  christos 	if (!ssid->bssid_hint_set)
    446  1.7  christos 		return NULL;
    447  1.7  christos 
    448  1.7  christos 	value = os_malloc(20);
    449  1.7  christos 	if (!value)
    450  1.7  christos 		return NULL;
    451  1.7  christos 	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid_hint));
    452  1.7  christos 	if (os_snprintf_error(20, res)) {
    453  1.7  christos 		os_free(value);
    454  1.7  christos 		return NULL;
    455  1.7  christos 	}
    456  1.7  christos 	return value;
    457  1.7  christos }
    458  1.7  christos #endif /* NO_CONFIG_WRITE */
    459  1.7  christos 
    460  1.7  christos 
    461  1.9  christos static int wpa_config_parse_bssid_ignore(const struct parse_data *data,
    462  1.9  christos 					 struct wpa_ssid *ssid, int line,
    463  1.9  christos 					 const char *value)
    464  1.9  christos {
    465  1.9  christos 	return wpa_config_parse_addr_list(data, line, value,
    466  1.9  christos 					  &ssid->bssid_ignore,
    467  1.9  christos 					  &ssid->num_bssid_ignore,
    468  1.9  christos 					  "bssid_ignore", 1, 1);
    469  1.9  christos }
    470  1.9  christos 
    471  1.9  christos 
    472  1.9  christos /* deprecated alias for bssid_ignore for backwards compatibility */
    473  1.2  christos static int wpa_config_parse_bssid_blacklist(const struct parse_data *data,
    474  1.2  christos 					    struct wpa_ssid *ssid, int line,
    475  1.2  christos 					    const char *value)
    476  1.2  christos {
    477  1.2  christos 	return wpa_config_parse_addr_list(data, line, value,
    478  1.9  christos 					  &ssid->bssid_ignore,
    479  1.9  christos 					  &ssid->num_bssid_ignore,
    480  1.9  christos 					  "bssid_ignore", 1, 1);
    481  1.2  christos }
    482  1.2  christos 
    483  1.2  christos 
    484  1.2  christos #ifndef NO_CONFIG_WRITE
    485  1.9  christos 
    486  1.9  christos static char * wpa_config_write_bssid_ignore(const struct parse_data *data,
    487  1.9  christos 					    struct wpa_ssid *ssid)
    488  1.9  christos {
    489  1.9  christos 	return wpa_config_write_addr_list(data, ssid->bssid_ignore,
    490  1.9  christos 					  ssid->num_bssid_ignore,
    491  1.9  christos 					  "bssid_ignore");
    492  1.9  christos }
    493  1.9  christos 
    494  1.9  christos 
    495  1.9  christos /* deprecated alias for bssid_ignore for backwards compatibility */
    496  1.2  christos static char * wpa_config_write_bssid_blacklist(const struct parse_data *data,
    497  1.2  christos 					       struct wpa_ssid *ssid)
    498  1.2  christos {
    499  1.9  christos 	return wpa_config_write_addr_list(data, ssid->bssid_ignore,
    500  1.9  christos 					  ssid->num_bssid_ignore,
    501  1.9  christos 					  "bssid_ignore");
    502  1.2  christos }
    503  1.9  christos 
    504  1.2  christos #endif /* NO_CONFIG_WRITE */
    505  1.2  christos 
    506  1.2  christos 
    507  1.9  christos static int wpa_config_parse_bssid_accept(const struct parse_data *data,
    508  1.9  christos 					 struct wpa_ssid *ssid, int line,
    509  1.9  christos 					 const char *value)
    510  1.9  christos {
    511  1.9  christos 	return wpa_config_parse_addr_list(data, line, value,
    512  1.9  christos 					  &ssid->bssid_accept,
    513  1.9  christos 					  &ssid->num_bssid_accept,
    514  1.9  christos 					  "bssid_accept", 1, 1);
    515  1.9  christos }
    516  1.9  christos 
    517  1.9  christos 
    518  1.9  christos /* deprecated alias for bssid_accept for backwards compatibility */
    519  1.2  christos static int wpa_config_parse_bssid_whitelist(const struct parse_data *data,
    520  1.2  christos 					    struct wpa_ssid *ssid, int line,
    521  1.2  christos 					    const char *value)
    522  1.2  christos {
    523  1.2  christos 	return wpa_config_parse_addr_list(data, line, value,
    524  1.9  christos 					  &ssid->bssid_accept,
    525  1.9  christos 					  &ssid->num_bssid_accept,
    526  1.9  christos 					  "bssid_accept", 1, 1);
    527  1.2  christos }
    528  1.2  christos 
    529  1.2  christos 
    530  1.2  christos #ifndef NO_CONFIG_WRITE
    531  1.9  christos 
    532  1.9  christos static char * wpa_config_write_bssid_accept(const struct parse_data *data,
    533  1.9  christos 					    struct wpa_ssid *ssid)
    534  1.9  christos {
    535  1.9  christos 	return wpa_config_write_addr_list(data, ssid->bssid_accept,
    536  1.9  christos 					  ssid->num_bssid_accept,
    537  1.9  christos 					  "bssid_accept");
    538  1.9  christos }
    539  1.9  christos 
    540  1.9  christos 
    541  1.9  christos /* deprecated alias for bssid_accept for backwards compatibility */
    542  1.2  christos static char * wpa_config_write_bssid_whitelist(const struct parse_data *data,
    543  1.2  christos 					       struct wpa_ssid *ssid)
    544  1.2  christos {
    545  1.9  christos 	return wpa_config_write_addr_list(data, ssid->bssid_accept,
    546  1.9  christos 					  ssid->num_bssid_accept,
    547  1.9  christos 					  "bssid_accept");
    548  1.2  christos }
    549  1.9  christos 
    550  1.9  christos #endif /* NO_CONFIG_WRITE */
    551  1.9  christos 
    552  1.9  christos 
    553  1.9  christos #ifndef NO_CONFIG_WRITE
    554  1.2  christos #endif /* NO_CONFIG_WRITE */
    555  1.2  christos 
    556  1.2  christos 
    557  1.1  christos static int wpa_config_parse_psk(const struct parse_data *data,
    558  1.1  christos 				struct wpa_ssid *ssid, int line,
    559  1.1  christos 				const char *value)
    560  1.1  christos {
    561  1.2  christos #ifdef CONFIG_EXT_PASSWORD
    562  1.2  christos 	if (os_strncmp(value, "ext:", 4) == 0) {
    563  1.2  christos 		str_clear_free(ssid->passphrase);
    564  1.2  christos 		ssid->passphrase = NULL;
    565  1.2  christos 		ssid->psk_set = 0;
    566  1.2  christos 		os_free(ssid->ext_psk);
    567  1.2  christos 		ssid->ext_psk = os_strdup(value + 4);
    568  1.2  christos 		if (ssid->ext_psk == NULL)
    569  1.2  christos 			return -1;
    570  1.2  christos 		wpa_printf(MSG_DEBUG, "PSK: External password '%s'",
    571  1.2  christos 			   ssid->ext_psk);
    572  1.2  christos 		return 0;
    573  1.2  christos 	}
    574  1.2  christos #endif /* CONFIG_EXT_PASSWORD */
    575  1.2  christos 
    576  1.1  christos 	if (*value == '"') {
    577  1.1  christos #ifndef CONFIG_NO_PBKDF2
    578  1.1  christos 		const char *pos;
    579  1.1  christos 		size_t len;
    580  1.1  christos 
    581  1.1  christos 		value++;
    582  1.1  christos 		pos = os_strrchr(value, '"');
    583  1.1  christos 		if (pos)
    584  1.1  christos 			len = pos - value;
    585  1.1  christos 		else
    586  1.1  christos 			len = os_strlen(value);
    587  1.1  christos 		if (len < 8 || len > 63) {
    588  1.1  christos 			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
    589  1.1  christos 				   "length %lu (expected: 8..63) '%s'.",
    590  1.1  christos 				   line, (unsigned long) len, value);
    591  1.1  christos 			return -1;
    592  1.1  christos 		}
    593  1.1  christos 		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
    594  1.1  christos 				      (u8 *) value, len);
    595  1.2  christos 		if (has_ctrl_char((u8 *) value, len)) {
    596  1.2  christos 			wpa_printf(MSG_ERROR,
    597  1.2  christos 				   "Line %d: Invalid passphrase character",
    598  1.2  christos 				   line);
    599  1.2  christos 			return -1;
    600  1.2  christos 		}
    601  1.1  christos 		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
    602  1.6  christos 		    os_memcmp(ssid->passphrase, value, len) == 0) {
    603  1.6  christos 			/* No change to the previously configured value */
    604  1.6  christos 			return 1;
    605  1.6  christos 		}
    606  1.1  christos 		ssid->psk_set = 0;
    607  1.2  christos 		str_clear_free(ssid->passphrase);
    608  1.2  christos 		ssid->passphrase = dup_binstr(value, len);
    609  1.1  christos 		if (ssid->passphrase == NULL)
    610  1.1  christos 			return -1;
    611  1.1  christos 		return 0;
    612  1.1  christos #else /* CONFIG_NO_PBKDF2 */
    613  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
    614  1.1  christos 			   "supported.", line);
    615  1.1  christos 		return -1;
    616  1.1  christos #endif /* CONFIG_NO_PBKDF2 */
    617  1.1  christos 	}
    618  1.1  christos 
    619  1.1  christos 	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
    620  1.1  christos 	    value[PMK_LEN * 2] != '\0') {
    621  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
    622  1.1  christos 			   line, value);
    623  1.1  christos 		return -1;
    624  1.1  christos 	}
    625  1.1  christos 
    626  1.2  christos 	str_clear_free(ssid->passphrase);
    627  1.1  christos 	ssid->passphrase = NULL;
    628  1.1  christos 
    629  1.1  christos 	ssid->psk_set = 1;
    630  1.1  christos 	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
    631  1.1  christos 	return 0;
    632  1.1  christos }
    633  1.1  christos 
    634  1.1  christos 
    635  1.1  christos #ifndef NO_CONFIG_WRITE
    636  1.1  christos static char * wpa_config_write_psk(const struct parse_data *data,
    637  1.1  christos 				   struct wpa_ssid *ssid)
    638  1.1  christos {
    639  1.2  christos #ifdef CONFIG_EXT_PASSWORD
    640  1.2  christos 	if (ssid->ext_psk) {
    641  1.2  christos 		size_t len = 4 + os_strlen(ssid->ext_psk) + 1;
    642  1.2  christos 		char *buf = os_malloc(len);
    643  1.2  christos 		int res;
    644  1.2  christos 
    645  1.2  christos 		if (buf == NULL)
    646  1.2  christos 			return NULL;
    647  1.2  christos 		res = os_snprintf(buf, len, "ext:%s", ssid->ext_psk);
    648  1.2  christos 		if (os_snprintf_error(len, res)) {
    649  1.2  christos 			os_free(buf);
    650  1.2  christos 			buf = NULL;
    651  1.2  christos 		}
    652  1.2  christos 		return buf;
    653  1.2  christos 	}
    654  1.2  christos #endif /* CONFIG_EXT_PASSWORD */
    655  1.2  christos 
    656  1.1  christos 	if (ssid->passphrase)
    657  1.1  christos 		return wpa_config_write_string_ascii(
    658  1.1  christos 			(const u8 *) ssid->passphrase,
    659  1.1  christos 			os_strlen(ssid->passphrase));
    660  1.1  christos 
    661  1.1  christos 	if (ssid->psk_set)
    662  1.1  christos 		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
    663  1.1  christos 
    664  1.1  christos 	return NULL;
    665  1.1  christos }
    666  1.1  christos #endif /* NO_CONFIG_WRITE */
    667  1.1  christos 
    668  1.1  christos 
    669  1.1  christos static int wpa_config_parse_proto(const struct parse_data *data,
    670  1.1  christos 				  struct wpa_ssid *ssid, int line,
    671  1.1  christos 				  const char *value)
    672  1.1  christos {
    673  1.1  christos 	int val = 0, last, errors = 0;
    674  1.1  christos 	char *start, *end, *buf;
    675  1.1  christos 
    676  1.1  christos 	buf = os_strdup(value);
    677  1.1  christos 	if (buf == NULL)
    678  1.1  christos 		return -1;
    679  1.1  christos 	start = buf;
    680  1.1  christos 
    681  1.1  christos 	while (*start != '\0') {
    682  1.1  christos 		while (*start == ' ' || *start == '\t')
    683  1.1  christos 			start++;
    684  1.1  christos 		if (*start == '\0')
    685  1.1  christos 			break;
    686  1.1  christos 		end = start;
    687  1.1  christos 		while (*end != ' ' && *end != '\t' && *end != '\0')
    688  1.1  christos 			end++;
    689  1.1  christos 		last = *end == '\0';
    690  1.1  christos 		*end = '\0';
    691  1.1  christos 		if (os_strcmp(start, "WPA") == 0)
    692  1.1  christos 			val |= WPA_PROTO_WPA;
    693  1.1  christos 		else if (os_strcmp(start, "RSN") == 0 ||
    694  1.1  christos 			 os_strcmp(start, "WPA2") == 0)
    695  1.1  christos 			val |= WPA_PROTO_RSN;
    696  1.2  christos 		else if (os_strcmp(start, "OSEN") == 0)
    697  1.2  christos 			val |= WPA_PROTO_OSEN;
    698  1.1  christos 		else {
    699  1.1  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
    700  1.1  christos 				   line, start);
    701  1.1  christos 			errors++;
    702  1.1  christos 		}
    703  1.1  christos 
    704  1.1  christos 		if (last)
    705  1.1  christos 			break;
    706  1.1  christos 		start = end + 1;
    707  1.1  christos 	}
    708  1.1  christos 	os_free(buf);
    709  1.1  christos 
    710  1.1  christos 	if (val == 0) {
    711  1.1  christos 		wpa_printf(MSG_ERROR,
    712  1.1  christos 			   "Line %d: no proto values configured.", line);
    713  1.1  christos 		errors++;
    714  1.1  christos 	}
    715  1.1  christos 
    716  1.6  christos 	if (!errors && ssid->proto == val)
    717  1.6  christos 		return 1;
    718  1.1  christos 	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
    719  1.1  christos 	ssid->proto = val;
    720  1.1  christos 	return errors ? -1 : 0;
    721  1.1  christos }
    722  1.1  christos 
    723  1.1  christos 
    724  1.1  christos #ifndef NO_CONFIG_WRITE
    725  1.1  christos static char * wpa_config_write_proto(const struct parse_data *data,
    726  1.1  christos 				     struct wpa_ssid *ssid)
    727  1.1  christos {
    728  1.2  christos 	int ret;
    729  1.1  christos 	char *buf, *pos, *end;
    730  1.1  christos 
    731  1.2  christos 	pos = buf = os_zalloc(20);
    732  1.1  christos 	if (buf == NULL)
    733  1.1  christos 		return NULL;
    734  1.2  christos 	end = buf + 20;
    735  1.1  christos 
    736  1.1  christos 	if (ssid->proto & WPA_PROTO_WPA) {
    737  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sWPA",
    738  1.2  christos 				  pos == buf ? "" : " ");
    739  1.2  christos 		if (os_snprintf_error(end - pos, ret))
    740  1.1  christos 			return buf;
    741  1.1  christos 		pos += ret;
    742  1.1  christos 	}
    743  1.1  christos 
    744  1.1  christos 	if (ssid->proto & WPA_PROTO_RSN) {
    745  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sRSN",
    746  1.2  christos 				  pos == buf ? "" : " ");
    747  1.2  christos 		if (os_snprintf_error(end - pos, ret))
    748  1.2  christos 			return buf;
    749  1.2  christos 		pos += ret;
    750  1.2  christos 	}
    751  1.2  christos 
    752  1.2  christos 	if (ssid->proto & WPA_PROTO_OSEN) {
    753  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sOSEN",
    754  1.2  christos 				  pos == buf ? "" : " ");
    755  1.2  christos 		if (os_snprintf_error(end - pos, ret))
    756  1.1  christos 			return buf;
    757  1.1  christos 		pos += ret;
    758  1.2  christos 	}
    759  1.2  christos 
    760  1.2  christos 	if (pos == buf) {
    761  1.2  christos 		os_free(buf);
    762  1.2  christos 		buf = NULL;
    763  1.1  christos 	}
    764  1.1  christos 
    765  1.1  christos 	return buf;
    766  1.1  christos }
    767  1.1  christos #endif /* NO_CONFIG_WRITE */
    768  1.1  christos 
    769  1.1  christos 
    770  1.1  christos static int wpa_config_parse_key_mgmt(const struct parse_data *data,
    771  1.1  christos 				     struct wpa_ssid *ssid, int line,
    772  1.1  christos 				     const char *value)
    773  1.1  christos {
    774  1.1  christos 	int val = 0, last, errors = 0;
    775  1.1  christos 	char *start, *end, *buf;
    776  1.1  christos 
    777  1.1  christos 	buf = os_strdup(value);
    778  1.1  christos 	if (buf == NULL)
    779  1.1  christos 		return -1;
    780  1.1  christos 	start = buf;
    781  1.1  christos 
    782  1.1  christos 	while (*start != '\0') {
    783  1.1  christos 		while (*start == ' ' || *start == '\t')
    784  1.1  christos 			start++;
    785  1.1  christos 		if (*start == '\0')
    786  1.1  christos 			break;
    787  1.1  christos 		end = start;
    788  1.1  christos 		while (*end != ' ' && *end != '\t' && *end != '\0')
    789  1.1  christos 			end++;
    790  1.1  christos 		last = *end == '\0';
    791  1.1  christos 		*end = '\0';
    792  1.1  christos 		if (os_strcmp(start, "WPA-PSK") == 0)
    793  1.1  christos 			val |= WPA_KEY_MGMT_PSK;
    794  1.1  christos 		else if (os_strcmp(start, "WPA-EAP") == 0)
    795  1.1  christos 			val |= WPA_KEY_MGMT_IEEE8021X;
    796  1.1  christos 		else if (os_strcmp(start, "IEEE8021X") == 0)
    797  1.1  christos 			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
    798  1.1  christos 		else if (os_strcmp(start, "NONE") == 0)
    799  1.1  christos 			val |= WPA_KEY_MGMT_NONE;
    800  1.1  christos 		else if (os_strcmp(start, "WPA-NONE") == 0)
    801  1.1  christos 			val |= WPA_KEY_MGMT_WPA_NONE;
    802  1.1  christos #ifdef CONFIG_IEEE80211R
    803  1.1  christos 		else if (os_strcmp(start, "FT-PSK") == 0)
    804  1.1  christos 			val |= WPA_KEY_MGMT_FT_PSK;
    805  1.1  christos 		else if (os_strcmp(start, "FT-EAP") == 0)
    806  1.1  christos 			val |= WPA_KEY_MGMT_FT_IEEE8021X;
    807  1.7  christos #ifdef CONFIG_SHA384
    808  1.7  christos 		else if (os_strcmp(start, "FT-EAP-SHA384") == 0)
    809  1.7  christos 			val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
    810  1.7  christos #endif /* CONFIG_SHA384 */
    811  1.1  christos #endif /* CONFIG_IEEE80211R */
    812  1.9  christos #ifdef CONFIG_SHA384
    813  1.9  christos 		else if (os_strcmp(start, "WPA-EAP-SHA384") == 0)
    814  1.9  christos 			val |= WPA_KEY_MGMT_IEEE8021X_SHA384;
    815  1.9  christos #endif /* CONFIG_SHA384 */
    816  1.1  christos 		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
    817  1.1  christos 			val |= WPA_KEY_MGMT_PSK_SHA256;
    818  1.1  christos 		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
    819  1.1  christos 			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
    820  1.1  christos #ifdef CONFIG_WPS
    821  1.1  christos 		else if (os_strcmp(start, "WPS") == 0)
    822  1.1  christos 			val |= WPA_KEY_MGMT_WPS;
    823  1.1  christos #endif /* CONFIG_WPS */
    824  1.2  christos #ifdef CONFIG_SAE
    825  1.2  christos 		else if (os_strcmp(start, "SAE") == 0)
    826  1.2  christos 			val |= WPA_KEY_MGMT_SAE;
    827  1.9  christos 		else if (os_strcmp(start, "SAE-EXT-KEY") == 0)
    828  1.9  christos 			val |= WPA_KEY_MGMT_SAE_EXT_KEY;
    829  1.2  christos 		else if (os_strcmp(start, "FT-SAE") == 0)
    830  1.2  christos 			val |= WPA_KEY_MGMT_FT_SAE;
    831  1.9  christos 		else if (os_strcmp(start, "FT-SAE-EXT-KEY") == 0)
    832  1.9  christos 			val |= WPA_KEY_MGMT_FT_SAE_EXT_KEY;
    833  1.2  christos #endif /* CONFIG_SAE */
    834  1.2  christos #ifdef CONFIG_HS20
    835  1.2  christos 		else if (os_strcmp(start, "OSEN") == 0)
    836  1.2  christos 			val |= WPA_KEY_MGMT_OSEN;
    837  1.2  christos #endif /* CONFIG_HS20 */
    838  1.2  christos #ifdef CONFIG_SUITEB
    839  1.2  christos 		else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
    840  1.2  christos 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
    841  1.2  christos #endif /* CONFIG_SUITEB */
    842  1.2  christos #ifdef CONFIG_SUITEB192
    843  1.2  christos 		else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
    844  1.2  christos 			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
    845  1.2  christos #endif /* CONFIG_SUITEB192 */
    846  1.7  christos #ifdef CONFIG_FILS
    847  1.7  christos 		else if (os_strcmp(start, "FILS-SHA256") == 0)
    848  1.7  christos 			val |= WPA_KEY_MGMT_FILS_SHA256;
    849  1.7  christos 		else if (os_strcmp(start, "FILS-SHA384") == 0)
    850  1.7  christos 			val |= WPA_KEY_MGMT_FILS_SHA384;
    851  1.7  christos #ifdef CONFIG_IEEE80211R
    852  1.7  christos 		else if (os_strcmp(start, "FT-FILS-SHA256") == 0)
    853  1.7  christos 			val |= WPA_KEY_MGMT_FT_FILS_SHA256;
    854  1.7  christos 		else if (os_strcmp(start, "FT-FILS-SHA384") == 0)
    855  1.7  christos 			val |= WPA_KEY_MGMT_FT_FILS_SHA384;
    856  1.7  christos #endif /* CONFIG_IEEE80211R */
    857  1.7  christos #endif /* CONFIG_FILS */
    858  1.7  christos #ifdef CONFIG_OWE
    859  1.7  christos 		else if (os_strcmp(start, "OWE") == 0)
    860  1.7  christos 			val |= WPA_KEY_MGMT_OWE;
    861  1.7  christos #endif /* CONFIG_OWE */
    862  1.7  christos #ifdef CONFIG_DPP
    863  1.7  christos 		else if (os_strcmp(start, "DPP") == 0)
    864  1.7  christos 			val |= WPA_KEY_MGMT_DPP;
    865  1.7  christos #endif /* CONFIG_DPP */
    866  1.1  christos 		else {
    867  1.1  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
    868  1.1  christos 				   line, start);
    869  1.1  christos 			errors++;
    870  1.1  christos 		}
    871  1.1  christos 
    872  1.1  christos 		if (last)
    873  1.1  christos 			break;
    874  1.1  christos 		start = end + 1;
    875  1.1  christos 	}
    876  1.1  christos 	os_free(buf);
    877  1.1  christos 
    878  1.1  christos 	if (val == 0) {
    879  1.1  christos 		wpa_printf(MSG_ERROR,
    880  1.1  christos 			   "Line %d: no key_mgmt values configured.", line);
    881  1.1  christos 		errors++;
    882  1.1  christos 	}
    883  1.1  christos 
    884  1.6  christos 	if (!errors && ssid->key_mgmt == val)
    885  1.6  christos 		return 1;
    886  1.1  christos 	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
    887  1.1  christos 	ssid->key_mgmt = val;
    888  1.1  christos 	return errors ? -1 : 0;
    889  1.1  christos }
    890  1.1  christos 
    891  1.1  christos 
    892  1.1  christos #ifndef NO_CONFIG_WRITE
    893  1.1  christos static char * wpa_config_write_key_mgmt(const struct parse_data *data,
    894  1.1  christos 					struct wpa_ssid *ssid)
    895  1.1  christos {
    896  1.1  christos 	char *buf, *pos, *end;
    897  1.1  christos 	int ret;
    898  1.1  christos 
    899  1.2  christos 	pos = buf = os_zalloc(100);
    900  1.1  christos 	if (buf == NULL)
    901  1.1  christos 		return NULL;
    902  1.2  christos 	end = buf + 100;
    903  1.1  christos 
    904  1.1  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
    905  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
    906  1.1  christos 				  pos == buf ? "" : " ");
    907  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    908  1.1  christos 			end[-1] = '\0';
    909  1.1  christos 			return buf;
    910  1.1  christos 		}
    911  1.1  christos 		pos += ret;
    912  1.1  christos 	}
    913  1.1  christos 
    914  1.1  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    915  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
    916  1.1  christos 				  pos == buf ? "" : " ");
    917  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    918  1.1  christos 			end[-1] = '\0';
    919  1.1  christos 			return buf;
    920  1.1  christos 		}
    921  1.1  christos 		pos += ret;
    922  1.1  christos 	}
    923  1.1  christos 
    924  1.1  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    925  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
    926  1.1  christos 				  pos == buf ? "" : " ");
    927  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    928  1.1  christos 			end[-1] = '\0';
    929  1.1  christos 			return buf;
    930  1.1  christos 		}
    931  1.1  christos 		pos += ret;
    932  1.1  christos 	}
    933  1.1  christos 
    934  1.1  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
    935  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sNONE",
    936  1.1  christos 				  pos == buf ? "" : " ");
    937  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    938  1.1  christos 			end[-1] = '\0';
    939  1.1  christos 			return buf;
    940  1.1  christos 		}
    941  1.1  christos 		pos += ret;
    942  1.1  christos 	}
    943  1.1  christos 
    944  1.1  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    945  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
    946  1.1  christos 				  pos == buf ? "" : " ");
    947  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    948  1.1  christos 			end[-1] = '\0';
    949  1.1  christos 			return buf;
    950  1.1  christos 		}
    951  1.1  christos 		pos += ret;
    952  1.1  christos 	}
    953  1.1  christos 
    954  1.1  christos #ifdef CONFIG_IEEE80211R
    955  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    956  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sFT-PSK",
    957  1.2  christos 				  pos == buf ? "" : " ");
    958  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    959  1.2  christos 			end[-1] = '\0';
    960  1.2  christos 			return buf;
    961  1.2  christos 		}
    962  1.2  christos 		pos += ret;
    963  1.2  christos 	}
    964  1.2  christos 
    965  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    966  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sFT-EAP",
    967  1.2  christos 				  pos == buf ? "" : " ");
    968  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
    969  1.2  christos 			end[-1] = '\0';
    970  1.2  christos 			return buf;
    971  1.2  christos 		}
    972  1.2  christos 		pos += ret;
    973  1.2  christos 	}
    974  1.7  christos 
    975  1.7  christos #ifdef CONFIG_SHA384
    976  1.7  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
    977  1.7  christos 		ret = os_snprintf(pos, end - pos, "%sFT-EAP-SHA384",
    978  1.7  christos 				  pos == buf ? "" : " ");
    979  1.7  christos 		if (os_snprintf_error(end - pos, ret)) {
    980  1.7  christos 			end[-1] = '\0';
    981  1.7  christos 			return buf;
    982  1.7  christos 		}
    983  1.7  christos 		pos += ret;
    984  1.7  christos 	}
    985  1.7  christos #endif /* CONFIG_SHA384 */
    986  1.1  christos #endif /* CONFIG_IEEE80211R */
    987  1.1  christos 
    988  1.9  christos #ifdef CONFIG_SHA384
    989  1.9  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
    990  1.9  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA384",
    991  1.9  christos 				  pos == buf ? "" : " ");
    992  1.9  christos 		if (os_snprintf_error(end - pos, ret)) {
    993  1.9  christos 			end[-1] = '\0';
    994  1.9  christos 			return buf;
    995  1.9  christos 		}
    996  1.9  christos 		pos += ret;
    997  1.9  christos 	}
    998  1.9  christos #endif /* CONFIG_SHA384 */
    999  1.9  christos 
   1000  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
   1001  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
   1002  1.2  christos 				  pos == buf ? "" : " ");
   1003  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1004  1.2  christos 			end[-1] = '\0';
   1005  1.2  christos 			return buf;
   1006  1.2  christos 		}
   1007  1.2  christos 		pos += ret;
   1008  1.2  christos 	}
   1009  1.2  christos 
   1010  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
   1011  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
   1012  1.2  christos 				  pos == buf ? "" : " ");
   1013  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1014  1.2  christos 			end[-1] = '\0';
   1015  1.2  christos 			return buf;
   1016  1.2  christos 		}
   1017  1.2  christos 		pos += ret;
   1018  1.2  christos 	}
   1019  1.1  christos 
   1020  1.1  christos #ifdef CONFIG_WPS
   1021  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
   1022  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sWPS",
   1023  1.2  christos 				  pos == buf ? "" : " ");
   1024  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1025  1.2  christos 			end[-1] = '\0';
   1026  1.2  christos 			return buf;
   1027  1.1  christos 		}
   1028  1.2  christos 		pos += ret;
   1029  1.1  christos 	}
   1030  1.2  christos #endif /* CONFIG_WPS */
   1031  1.1  christos 
   1032  1.2  christos #ifdef CONFIG_SAE
   1033  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
   1034  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sSAE",
   1035  1.1  christos 				  pos == buf ? "" : " ");
   1036  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1037  1.1  christos 			end[-1] = '\0';
   1038  1.1  christos 			return buf;
   1039  1.1  christos 		}
   1040  1.1  christos 		pos += ret;
   1041  1.1  christos 	}
   1042  1.1  christos 
   1043  1.9  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
   1044  1.9  christos 		ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY",
   1045  1.9  christos 				  pos == buf ? "" : " ");
   1046  1.9  christos 		if (os_snprintf_error(end - pos, ret)) {
   1047  1.9  christos 			end[-1] = '\0';
   1048  1.9  christos 			return buf;
   1049  1.9  christos 		}
   1050  1.9  christos 		pos += ret;
   1051  1.9  christos 	}
   1052  1.9  christos 
   1053  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_SAE) {
   1054  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sFT-SAE",
   1055  1.1  christos 				  pos == buf ? "" : " ");
   1056  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1057  1.1  christos 			end[-1] = '\0';
   1058  1.1  christos 			return buf;
   1059  1.1  christos 		}
   1060  1.1  christos 		pos += ret;
   1061  1.1  christos 	}
   1062  1.9  christos 
   1063  1.9  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
   1064  1.9  christos 		ret = os_snprintf(pos, end - pos, "%sFT-SAE-EXT-KEY",
   1065  1.9  christos 				  pos == buf ? "" : " ");
   1066  1.9  christos 		if (os_snprintf_error(end - pos, ret)) {
   1067  1.9  christos 			end[-1] = '\0';
   1068  1.9  christos 			return buf;
   1069  1.9  christos 		}
   1070  1.9  christos 		pos += ret;
   1071  1.9  christos 	}
   1072  1.2  christos #endif /* CONFIG_SAE */
   1073  1.1  christos 
   1074  1.2  christos #ifdef CONFIG_HS20
   1075  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN) {
   1076  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sOSEN",
   1077  1.1  christos 				  pos == buf ? "" : " ");
   1078  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1079  1.1  christos 			end[-1] = '\0';
   1080  1.1  christos 			return buf;
   1081  1.1  christos 		}
   1082  1.1  christos 		pos += ret;
   1083  1.1  christos 	}
   1084  1.2  christos #endif /* CONFIG_HS20 */
   1085  1.1  christos 
   1086  1.2  christos #ifdef CONFIG_SUITEB
   1087  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
   1088  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B",
   1089  1.1  christos 				  pos == buf ? "" : " ");
   1090  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1091  1.1  christos 			end[-1] = '\0';
   1092  1.1  christos 			return buf;
   1093  1.1  christos 		}
   1094  1.1  christos 		pos += ret;
   1095  1.1  christos 	}
   1096  1.2  christos #endif /* CONFIG_SUITEB */
   1097  1.1  christos 
   1098  1.2  christos #ifdef CONFIG_SUITEB192
   1099  1.2  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
   1100  1.2  christos 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B-192",
   1101  1.1  christos 				  pos == buf ? "" : " ");
   1102  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1103  1.1  christos 			end[-1] = '\0';
   1104  1.1  christos 			return buf;
   1105  1.1  christos 		}
   1106  1.1  christos 		pos += ret;
   1107  1.1  christos 	}
   1108  1.2  christos #endif /* CONFIG_SUITEB192 */
   1109  1.2  christos 
   1110  1.7  christos #ifdef CONFIG_FILS
   1111  1.7  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
   1112  1.7  christos 		ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
   1113  1.7  christos 				  pos == buf ? "" : " ");
   1114  1.7  christos 		if (os_snprintf_error(end - pos, ret)) {
   1115  1.7  christos 			end[-1] = '\0';
   1116  1.7  christos 			return buf;
   1117  1.7  christos 		}
   1118  1.7  christos 		pos += ret;
   1119  1.7  christos 	}
   1120  1.7  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
   1121  1.7  christos 		ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
   1122  1.7  christos 				  pos == buf ? "" : " ");
   1123  1.7  christos 		if (os_snprintf_error(end - pos, ret)) {
   1124  1.7  christos 			end[-1] = '\0';
   1125  1.7  christos 			return buf;
   1126  1.7  christos 		}
   1127  1.7  christos 		pos += ret;
   1128  1.7  christos 	}
   1129  1.7  christos #ifdef CONFIG_IEEE80211R
   1130  1.7  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
   1131  1.7  christos 		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
   1132  1.7  christos 				  pos == buf ? "" : " ");
   1133  1.7  christos 		if (os_snprintf_error(end - pos, ret)) {
   1134  1.7  christos 			end[-1] = '\0';
   1135  1.7  christos 			return buf;
   1136  1.7  christos 		}
   1137  1.7  christos 		pos += ret;
   1138  1.7  christos 	}
   1139  1.7  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
   1140  1.7  christos 		ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
   1141  1.7  christos 				  pos == buf ? "" : " ");
   1142  1.7  christos 		if (os_snprintf_error(end - pos, ret)) {
   1143  1.7  christos 			end[-1] = '\0';
   1144  1.7  christos 			return buf;
   1145  1.7  christos 		}
   1146  1.7  christos 		pos += ret;
   1147  1.7  christos 	}
   1148  1.7  christos #endif /* CONFIG_IEEE80211R */
   1149  1.7  christos #endif /* CONFIG_FILS */
   1150  1.7  christos 
   1151  1.8  christos #ifdef CONFIG_DPP
   1152  1.8  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_DPP) {
   1153  1.8  christos 		ret = os_snprintf(pos, end - pos, "%sDPP",
   1154  1.8  christos 				  pos == buf ? "" : " ");
   1155  1.8  christos 		if (os_snprintf_error(end - pos, ret)) {
   1156  1.8  christos 			end[-1] = '\0';
   1157  1.8  christos 			return buf;
   1158  1.8  christos 		}
   1159  1.8  christos 		pos += ret;
   1160  1.8  christos 	}
   1161  1.8  christos #endif /* CONFIG_DPP */
   1162  1.8  christos 
   1163  1.8  christos #ifdef CONFIG_OWE
   1164  1.8  christos 	if (ssid->key_mgmt & WPA_KEY_MGMT_OWE) {
   1165  1.8  christos 		ret = os_snprintf(pos, end - pos, "%sOWE",
   1166  1.8  christos 				  pos == buf ? "" : " ");
   1167  1.8  christos 		if (os_snprintf_error(end - pos, ret)) {
   1168  1.8  christos 			end[-1] = '\0';
   1169  1.8  christos 			return buf;
   1170  1.8  christos 		}
   1171  1.8  christos 		pos += ret;
   1172  1.8  christos 	}
   1173  1.8  christos #endif /* CONFIG_OWE */
   1174  1.8  christos 
   1175  1.2  christos 	if (pos == buf) {
   1176  1.2  christos 		os_free(buf);
   1177  1.2  christos 		buf = NULL;
   1178  1.2  christos 	}
   1179  1.2  christos 
   1180  1.2  christos 	return buf;
   1181  1.2  christos }
   1182  1.2  christos #endif /* NO_CONFIG_WRITE */
   1183  1.2  christos 
   1184  1.2  christos 
   1185  1.2  christos static int wpa_config_parse_cipher(int line, const char *value)
   1186  1.2  christos {
   1187  1.6  christos #ifdef CONFIG_NO_WPA
   1188  1.6  christos 	return -1;
   1189  1.6  christos #else /* CONFIG_NO_WPA */
   1190  1.2  christos 	int val = wpa_parse_cipher(value);
   1191  1.2  christos 	if (val < 0) {
   1192  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
   1193  1.2  christos 			   line, value);
   1194  1.2  christos 		return -1;
   1195  1.2  christos 	}
   1196  1.2  christos 	if (val == 0) {
   1197  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
   1198  1.2  christos 			   line);
   1199  1.2  christos 		return -1;
   1200  1.2  christos 	}
   1201  1.2  christos 	return val;
   1202  1.6  christos #endif /* CONFIG_NO_WPA */
   1203  1.2  christos }
   1204  1.2  christos 
   1205  1.2  christos 
   1206  1.2  christos #ifndef NO_CONFIG_WRITE
   1207  1.2  christos static char * wpa_config_write_cipher(int cipher)
   1208  1.2  christos {
   1209  1.6  christos #ifdef CONFIG_NO_WPA
   1210  1.6  christos 	return NULL;
   1211  1.6  christos #else /* CONFIG_NO_WPA */
   1212  1.2  christos 	char *buf = os_zalloc(50);
   1213  1.2  christos 	if (buf == NULL)
   1214  1.2  christos 		return NULL;
   1215  1.2  christos 
   1216  1.2  christos 	if (wpa_write_ciphers(buf, buf + 50, cipher, " ") < 0) {
   1217  1.2  christos 		os_free(buf);
   1218  1.2  christos 		return NULL;
   1219  1.2  christos 	}
   1220  1.1  christos 
   1221  1.1  christos 	return buf;
   1222  1.6  christos #endif /* CONFIG_NO_WPA */
   1223  1.1  christos }
   1224  1.1  christos #endif /* NO_CONFIG_WRITE */
   1225  1.1  christos 
   1226  1.1  christos 
   1227  1.1  christos static int wpa_config_parse_pairwise(const struct parse_data *data,
   1228  1.1  christos 				     struct wpa_ssid *ssid, int line,
   1229  1.1  christos 				     const char *value)
   1230  1.1  christos {
   1231  1.1  christos 	int val;
   1232  1.1  christos 	val = wpa_config_parse_cipher(line, value);
   1233  1.1  christos 	if (val == -1)
   1234  1.1  christos 		return -1;
   1235  1.2  christos 	if (val & ~WPA_ALLOWED_PAIRWISE_CIPHERS) {
   1236  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
   1237  1.1  christos 			   "(0x%x).", line, val);
   1238  1.1  christos 		return -1;
   1239  1.1  christos 	}
   1240  1.1  christos 
   1241  1.6  christos 	if (ssid->pairwise_cipher == val)
   1242  1.6  christos 		return 1;
   1243  1.1  christos 	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
   1244  1.1  christos 	ssid->pairwise_cipher = val;
   1245  1.1  christos 	return 0;
   1246  1.1  christos }
   1247  1.1  christos 
   1248  1.1  christos 
   1249  1.1  christos #ifndef NO_CONFIG_WRITE
   1250  1.1  christos static char * wpa_config_write_pairwise(const struct parse_data *data,
   1251  1.1  christos 					struct wpa_ssid *ssid)
   1252  1.1  christos {
   1253  1.1  christos 	return wpa_config_write_cipher(ssid->pairwise_cipher);
   1254  1.1  christos }
   1255  1.1  christos #endif /* NO_CONFIG_WRITE */
   1256  1.1  christos 
   1257  1.1  christos 
   1258  1.1  christos static int wpa_config_parse_group(const struct parse_data *data,
   1259  1.1  christos 				  struct wpa_ssid *ssid, int line,
   1260  1.1  christos 				  const char *value)
   1261  1.1  christos {
   1262  1.1  christos 	int val;
   1263  1.1  christos 	val = wpa_config_parse_cipher(line, value);
   1264  1.1  christos 	if (val == -1)
   1265  1.1  christos 		return -1;
   1266  1.6  christos 
   1267  1.6  christos 	/*
   1268  1.6  christos 	 * Backwards compatibility - filter out WEP ciphers that were previously
   1269  1.6  christos 	 * allowed.
   1270  1.6  christos 	 */
   1271  1.6  christos 	val &= ~(WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40);
   1272  1.6  christos 
   1273  1.2  christos 	if (val & ~WPA_ALLOWED_GROUP_CIPHERS) {
   1274  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
   1275  1.1  christos 			   "(0x%x).", line, val);
   1276  1.1  christos 		return -1;
   1277  1.1  christos 	}
   1278  1.1  christos 
   1279  1.6  christos 	if (ssid->group_cipher == val)
   1280  1.6  christos 		return 1;
   1281  1.1  christos 	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
   1282  1.1  christos 	ssid->group_cipher = val;
   1283  1.1  christos 	return 0;
   1284  1.1  christos }
   1285  1.1  christos 
   1286  1.1  christos 
   1287  1.1  christos #ifndef NO_CONFIG_WRITE
   1288  1.1  christos static char * wpa_config_write_group(const struct parse_data *data,
   1289  1.1  christos 				     struct wpa_ssid *ssid)
   1290  1.1  christos {
   1291  1.1  christos 	return wpa_config_write_cipher(ssid->group_cipher);
   1292  1.1  christos }
   1293  1.1  christos #endif /* NO_CONFIG_WRITE */
   1294  1.1  christos 
   1295  1.1  christos 
   1296  1.7  christos static int wpa_config_parse_group_mgmt(const struct parse_data *data,
   1297  1.7  christos 				       struct wpa_ssid *ssid, int line,
   1298  1.7  christos 				       const char *value)
   1299  1.7  christos {
   1300  1.7  christos 	int val;
   1301  1.7  christos 
   1302  1.7  christos 	val = wpa_config_parse_cipher(line, value);
   1303  1.7  christos 	if (val == -1)
   1304  1.7  christos 		return -1;
   1305  1.7  christos 
   1306  1.7  christos 	if (val & ~WPA_ALLOWED_GROUP_MGMT_CIPHERS) {
   1307  1.7  christos 		wpa_printf(MSG_ERROR,
   1308  1.7  christos 			   "Line %d: not allowed group management cipher (0x%x).",
   1309  1.7  christos 			   line, val);
   1310  1.7  christos 		return -1;
   1311  1.7  christos 	}
   1312  1.7  christos 
   1313  1.7  christos 	if (ssid->group_mgmt_cipher == val)
   1314  1.7  christos 		return 1;
   1315  1.7  christos 	wpa_printf(MSG_MSGDUMP, "group_mgmt: 0x%x", val);
   1316  1.7  christos 	ssid->group_mgmt_cipher = val;
   1317  1.7  christos 	return 0;
   1318  1.7  christos }
   1319  1.7  christos 
   1320  1.7  christos 
   1321  1.7  christos #ifndef NO_CONFIG_WRITE
   1322  1.7  christos static char * wpa_config_write_group_mgmt(const struct parse_data *data,
   1323  1.7  christos 					  struct wpa_ssid *ssid)
   1324  1.7  christos {
   1325  1.7  christos 	return wpa_config_write_cipher(ssid->group_mgmt_cipher);
   1326  1.7  christos }
   1327  1.7  christos #endif /* NO_CONFIG_WRITE */
   1328  1.7  christos 
   1329  1.7  christos 
   1330  1.1  christos static int wpa_config_parse_auth_alg(const struct parse_data *data,
   1331  1.1  christos 				     struct wpa_ssid *ssid, int line,
   1332  1.1  christos 				     const char *value)
   1333  1.1  christos {
   1334  1.1  christos 	int val = 0, last, errors = 0;
   1335  1.1  christos 	char *start, *end, *buf;
   1336  1.1  christos 
   1337  1.1  christos 	buf = os_strdup(value);
   1338  1.1  christos 	if (buf == NULL)
   1339  1.1  christos 		return -1;
   1340  1.1  christos 	start = buf;
   1341  1.1  christos 
   1342  1.1  christos 	while (*start != '\0') {
   1343  1.1  christos 		while (*start == ' ' || *start == '\t')
   1344  1.1  christos 			start++;
   1345  1.1  christos 		if (*start == '\0')
   1346  1.1  christos 			break;
   1347  1.1  christos 		end = start;
   1348  1.1  christos 		while (*end != ' ' && *end != '\t' && *end != '\0')
   1349  1.1  christos 			end++;
   1350  1.1  christos 		last = *end == '\0';
   1351  1.1  christos 		*end = '\0';
   1352  1.1  christos 		if (os_strcmp(start, "OPEN") == 0)
   1353  1.1  christos 			val |= WPA_AUTH_ALG_OPEN;
   1354  1.1  christos 		else if (os_strcmp(start, "SHARED") == 0)
   1355  1.1  christos 			val |= WPA_AUTH_ALG_SHARED;
   1356  1.1  christos 		else if (os_strcmp(start, "LEAP") == 0)
   1357  1.1  christos 			val |= WPA_AUTH_ALG_LEAP;
   1358  1.1  christos 		else {
   1359  1.1  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
   1360  1.1  christos 				   line, start);
   1361  1.1  christos 			errors++;
   1362  1.1  christos 		}
   1363  1.1  christos 
   1364  1.1  christos 		if (last)
   1365  1.1  christos 			break;
   1366  1.1  christos 		start = end + 1;
   1367  1.1  christos 	}
   1368  1.1  christos 	os_free(buf);
   1369  1.1  christos 
   1370  1.1  christos 	if (val == 0) {
   1371  1.1  christos 		wpa_printf(MSG_ERROR,
   1372  1.1  christos 			   "Line %d: no auth_alg values configured.", line);
   1373  1.1  christos 		errors++;
   1374  1.1  christos 	}
   1375  1.1  christos 
   1376  1.6  christos 	if (!errors && ssid->auth_alg == val)
   1377  1.6  christos 		return 1;
   1378  1.1  christos 	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
   1379  1.1  christos 	ssid->auth_alg = val;
   1380  1.1  christos 	return errors ? -1 : 0;
   1381  1.1  christos }
   1382  1.1  christos 
   1383  1.1  christos 
   1384  1.1  christos #ifndef NO_CONFIG_WRITE
   1385  1.1  christos static char * wpa_config_write_auth_alg(const struct parse_data *data,
   1386  1.1  christos 					struct wpa_ssid *ssid)
   1387  1.1  christos {
   1388  1.1  christos 	char *buf, *pos, *end;
   1389  1.1  christos 	int ret;
   1390  1.1  christos 
   1391  1.1  christos 	pos = buf = os_zalloc(30);
   1392  1.1  christos 	if (buf == NULL)
   1393  1.1  christos 		return NULL;
   1394  1.1  christos 	end = buf + 30;
   1395  1.1  christos 
   1396  1.1  christos 	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
   1397  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sOPEN",
   1398  1.1  christos 				  pos == buf ? "" : " ");
   1399  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1400  1.1  christos 			end[-1] = '\0';
   1401  1.1  christos 			return buf;
   1402  1.1  christos 		}
   1403  1.1  christos 		pos += ret;
   1404  1.1  christos 	}
   1405  1.1  christos 
   1406  1.1  christos 	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
   1407  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sSHARED",
   1408  1.1  christos 				  pos == buf ? "" : " ");
   1409  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1410  1.1  christos 			end[-1] = '\0';
   1411  1.1  christos 			return buf;
   1412  1.1  christos 		}
   1413  1.1  christos 		pos += ret;
   1414  1.1  christos 	}
   1415  1.1  christos 
   1416  1.1  christos 	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
   1417  1.1  christos 		ret = os_snprintf(pos, end - pos, "%sLEAP",
   1418  1.1  christos 				  pos == buf ? "" : " ");
   1419  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1420  1.1  christos 			end[-1] = '\0';
   1421  1.1  christos 			return buf;
   1422  1.1  christos 		}
   1423  1.1  christos 		pos += ret;
   1424  1.1  christos 	}
   1425  1.1  christos 
   1426  1.2  christos 	if (pos == buf) {
   1427  1.2  christos 		os_free(buf);
   1428  1.2  christos 		buf = NULL;
   1429  1.2  christos 	}
   1430  1.2  christos 
   1431  1.1  christos 	return buf;
   1432  1.1  christos }
   1433  1.1  christos #endif /* NO_CONFIG_WRITE */
   1434  1.1  christos 
   1435  1.1  christos 
   1436  1.2  christos static int * wpa_config_parse_int_array(const char *value)
   1437  1.1  christos {
   1438  1.1  christos 	int *freqs;
   1439  1.1  christos 	size_t used, len;
   1440  1.1  christos 	const char *pos;
   1441  1.1  christos 
   1442  1.1  christos 	used = 0;
   1443  1.1  christos 	len = 10;
   1444  1.2  christos 	freqs = os_calloc(len + 1, sizeof(int));
   1445  1.1  christos 	if (freqs == NULL)
   1446  1.1  christos 		return NULL;
   1447  1.1  christos 
   1448  1.1  christos 	pos = value;
   1449  1.1  christos 	while (pos) {
   1450  1.1  christos 		while (*pos == ' ')
   1451  1.1  christos 			pos++;
   1452  1.1  christos 		if (used == len) {
   1453  1.1  christos 			int *n;
   1454  1.1  christos 			size_t i;
   1455  1.2  christos 			n = os_realloc_array(freqs, len * 2 + 1, sizeof(int));
   1456  1.1  christos 			if (n == NULL) {
   1457  1.1  christos 				os_free(freqs);
   1458  1.1  christos 				return NULL;
   1459  1.1  christos 			}
   1460  1.1  christos 			for (i = len; i <= len * 2; i++)
   1461  1.1  christos 				n[i] = 0;
   1462  1.1  christos 			freqs = n;
   1463  1.1  christos 			len *= 2;
   1464  1.1  christos 		}
   1465  1.1  christos 
   1466  1.1  christos 		freqs[used] = atoi(pos);
   1467  1.1  christos 		if (freqs[used] == 0)
   1468  1.1  christos 			break;
   1469  1.1  christos 		used++;
   1470  1.1  christos 		pos = os_strchr(pos + 1, ' ');
   1471  1.1  christos 	}
   1472  1.1  christos 
   1473  1.1  christos 	return freqs;
   1474  1.1  christos }
   1475  1.1  christos 
   1476  1.1  christos 
   1477  1.1  christos static int wpa_config_parse_scan_freq(const struct parse_data *data,
   1478  1.1  christos 				      struct wpa_ssid *ssid, int line,
   1479  1.1  christos 				      const char *value)
   1480  1.1  christos {
   1481  1.1  christos 	int *freqs;
   1482  1.1  christos 
   1483  1.2  christos 	freqs = wpa_config_parse_int_array(value);
   1484  1.1  christos 	if (freqs == NULL)
   1485  1.1  christos 		return -1;
   1486  1.2  christos 	if (freqs[0] == 0) {
   1487  1.2  christos 		os_free(freqs);
   1488  1.2  christos 		freqs = NULL;
   1489  1.2  christos 	}
   1490  1.1  christos 	os_free(ssid->scan_freq);
   1491  1.1  christos 	ssid->scan_freq = freqs;
   1492  1.1  christos 
   1493  1.1  christos 	return 0;
   1494  1.1  christos }
   1495  1.1  christos 
   1496  1.1  christos 
   1497  1.1  christos static int wpa_config_parse_freq_list(const struct parse_data *data,
   1498  1.1  christos 				      struct wpa_ssid *ssid, int line,
   1499  1.1  christos 				      const char *value)
   1500  1.1  christos {
   1501  1.1  christos 	int *freqs;
   1502  1.1  christos 
   1503  1.2  christos 	freqs = wpa_config_parse_int_array(value);
   1504  1.1  christos 	if (freqs == NULL)
   1505  1.1  christos 		return -1;
   1506  1.2  christos 	if (freqs[0] == 0) {
   1507  1.2  christos 		os_free(freqs);
   1508  1.2  christos 		freqs = NULL;
   1509  1.2  christos 	}
   1510  1.1  christos 	os_free(ssid->freq_list);
   1511  1.1  christos 	ssid->freq_list = freqs;
   1512  1.1  christos 
   1513  1.1  christos 	return 0;
   1514  1.1  christos }
   1515  1.1  christos 
   1516  1.1  christos 
   1517  1.1  christos #ifndef NO_CONFIG_WRITE
   1518  1.1  christos static char * wpa_config_write_freqs(const struct parse_data *data,
   1519  1.1  christos 				     const int *freqs)
   1520  1.1  christos {
   1521  1.1  christos 	char *buf, *pos, *end;
   1522  1.1  christos 	int i, ret;
   1523  1.1  christos 	size_t count;
   1524  1.1  christos 
   1525  1.1  christos 	if (freqs == NULL)
   1526  1.1  christos 		return NULL;
   1527  1.1  christos 
   1528  1.1  christos 	count = 0;
   1529  1.1  christos 	for (i = 0; freqs[i]; i++)
   1530  1.1  christos 		count++;
   1531  1.1  christos 
   1532  1.1  christos 	pos = buf = os_zalloc(10 * count + 1);
   1533  1.1  christos 	if (buf == NULL)
   1534  1.1  christos 		return NULL;
   1535  1.1  christos 	end = buf + 10 * count + 1;
   1536  1.1  christos 
   1537  1.1  christos 	for (i = 0; freqs[i]; i++) {
   1538  1.1  christos 		ret = os_snprintf(pos, end - pos, "%s%u",
   1539  1.1  christos 				  i == 0 ? "" : " ", freqs[i]);
   1540  1.2  christos 		if (os_snprintf_error(end - pos, ret)) {
   1541  1.1  christos 			end[-1] = '\0';
   1542  1.1  christos 			return buf;
   1543  1.1  christos 		}
   1544  1.1  christos 		pos += ret;
   1545  1.1  christos 	}
   1546  1.1  christos 
   1547  1.1  christos 	return buf;
   1548  1.1  christos }
   1549  1.1  christos 
   1550  1.1  christos 
   1551  1.1  christos static char * wpa_config_write_scan_freq(const struct parse_data *data,
   1552  1.1  christos 					 struct wpa_ssid *ssid)
   1553  1.1  christos {
   1554  1.1  christos 	return wpa_config_write_freqs(data, ssid->scan_freq);
   1555  1.1  christos }
   1556  1.1  christos 
   1557  1.1  christos 
   1558  1.1  christos static char * wpa_config_write_freq_list(const struct parse_data *data,
   1559  1.1  christos 					 struct wpa_ssid *ssid)
   1560  1.1  christos {
   1561  1.1  christos 	return wpa_config_write_freqs(data, ssid->freq_list);
   1562  1.1  christos }
   1563  1.1  christos #endif /* NO_CONFIG_WRITE */
   1564  1.1  christos 
   1565  1.1  christos 
   1566  1.1  christos #ifdef IEEE8021X_EAPOL
   1567  1.1  christos static int wpa_config_parse_eap(const struct parse_data *data,
   1568  1.1  christos 				struct wpa_ssid *ssid, int line,
   1569  1.1  christos 				const char *value)
   1570  1.1  christos {
   1571  1.1  christos 	int last, errors = 0;
   1572  1.1  christos 	char *start, *end, *buf;
   1573  1.1  christos 	struct eap_method_type *methods = NULL, *tmp;
   1574  1.1  christos 	size_t num_methods = 0;
   1575  1.1  christos 
   1576  1.1  christos 	buf = os_strdup(value);
   1577  1.1  christos 	if (buf == NULL)
   1578  1.1  christos 		return -1;
   1579  1.1  christos 	start = buf;
   1580  1.1  christos 
   1581  1.1  christos 	while (*start != '\0') {
   1582  1.1  christos 		while (*start == ' ' || *start == '\t')
   1583  1.1  christos 			start++;
   1584  1.1  christos 		if (*start == '\0')
   1585  1.1  christos 			break;
   1586  1.1  christos 		end = start;
   1587  1.1  christos 		while (*end != ' ' && *end != '\t' && *end != '\0')
   1588  1.1  christos 			end++;
   1589  1.1  christos 		last = *end == '\0';
   1590  1.1  christos 		*end = '\0';
   1591  1.1  christos 		tmp = methods;
   1592  1.2  christos 		methods = os_realloc_array(methods, num_methods + 1,
   1593  1.2  christos 					   sizeof(*methods));
   1594  1.1  christos 		if (methods == NULL) {
   1595  1.1  christos 			os_free(tmp);
   1596  1.1  christos 			os_free(buf);
   1597  1.1  christos 			return -1;
   1598  1.1  christos 		}
   1599  1.1  christos 		methods[num_methods].method = eap_peer_get_type(
   1600  1.1  christos 			start, &methods[num_methods].vendor);
   1601  1.1  christos 		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
   1602  1.1  christos 		    methods[num_methods].method == EAP_TYPE_NONE) {
   1603  1.1  christos 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
   1604  1.1  christos 				   "'%s'", line, start);
   1605  1.1  christos 			wpa_printf(MSG_ERROR, "You may need to add support for"
   1606  1.1  christos 				   " this EAP method during wpa_supplicant\n"
   1607  1.1  christos 				   "build time configuration.\n"
   1608  1.1  christos 				   "See README for more information.");
   1609  1.1  christos 			errors++;
   1610  1.1  christos 		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
   1611  1.1  christos 			   methods[num_methods].method == EAP_TYPE_LEAP)
   1612  1.1  christos 			ssid->leap++;
   1613  1.1  christos 		else
   1614  1.1  christos 			ssid->non_leap++;
   1615  1.1  christos 		num_methods++;
   1616  1.1  christos 		if (last)
   1617  1.1  christos 			break;
   1618  1.1  christos 		start = end + 1;
   1619  1.1  christos 	}
   1620  1.1  christos 	os_free(buf);
   1621  1.1  christos 
   1622  1.1  christos 	tmp = methods;
   1623  1.2  christos 	methods = os_realloc_array(methods, num_methods + 1, sizeof(*methods));
   1624  1.1  christos 	if (methods == NULL) {
   1625  1.1  christos 		os_free(tmp);
   1626  1.1  christos 		return -1;
   1627  1.1  christos 	}
   1628  1.1  christos 	methods[num_methods].vendor = EAP_VENDOR_IETF;
   1629  1.1  christos 	methods[num_methods].method = EAP_TYPE_NONE;
   1630  1.1  christos 	num_methods++;
   1631  1.1  christos 
   1632  1.6  christos 	if (!errors && ssid->eap.eap_methods) {
   1633  1.6  christos 		struct eap_method_type *prev_m;
   1634  1.6  christos 		size_t i, j, prev_methods, match = 0;
   1635  1.6  christos 
   1636  1.6  christos 		prev_m = ssid->eap.eap_methods;
   1637  1.6  christos 		for (i = 0; prev_m[i].vendor != EAP_VENDOR_IETF ||
   1638  1.6  christos 			     prev_m[i].method != EAP_TYPE_NONE; i++) {
   1639  1.6  christos 			/* Count the methods */
   1640  1.6  christos 		}
   1641  1.6  christos 		prev_methods = i + 1;
   1642  1.6  christos 
   1643  1.6  christos 		for (i = 0; prev_methods == num_methods && i < prev_methods;
   1644  1.6  christos 		     i++) {
   1645  1.6  christos 			for (j = 0; j < num_methods; j++) {
   1646  1.6  christos 				if (prev_m[i].vendor == methods[j].vendor &&
   1647  1.6  christos 				    prev_m[i].method == methods[j].method) {
   1648  1.6  christos 					match++;
   1649  1.6  christos 					break;
   1650  1.6  christos 				}
   1651  1.6  christos 			}
   1652  1.6  christos 		}
   1653  1.6  christos 		if (match == num_methods) {
   1654  1.6  christos 			os_free(methods);
   1655  1.6  christos 			return 1;
   1656  1.6  christos 		}
   1657  1.6  christos 	}
   1658  1.1  christos 	wpa_hexdump(MSG_MSGDUMP, "eap methods",
   1659  1.1  christos 		    (u8 *) methods, num_methods * sizeof(*methods));
   1660  1.2  christos 	os_free(ssid->eap.eap_methods);
   1661  1.1  christos 	ssid->eap.eap_methods = methods;
   1662  1.1  christos 	return errors ? -1 : 0;
   1663  1.1  christos }
   1664  1.1  christos 
   1665  1.1  christos 
   1666  1.6  christos #ifndef NO_CONFIG_WRITE
   1667  1.1  christos static char * wpa_config_write_eap(const struct parse_data *data,
   1668  1.1  christos 				   struct wpa_ssid *ssid)
   1669  1.1  christos {
   1670  1.1  christos 	int i, ret;
   1671  1.1  christos 	char *buf, *pos, *end;
   1672  1.1  christos 	const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
   1673  1.1  christos 	const char *name;
   1674  1.1  christos 
   1675  1.1  christos 	if (eap_methods == NULL)
   1676  1.1  christos 		return NULL;
   1677  1.1  christos 
   1678  1.1  christos 	pos = buf = os_zalloc(100);
   1679  1.1  christos 	if (buf == NULL)
   1680  1.1  christos 		return NULL;
   1681  1.1  christos 	end = buf + 100;
   1682  1.1  christos 
   1683  1.1  christos 	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
   1684  1.1  christos 		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
   1685  1.1  christos 		name = eap_get_name(eap_methods[i].vendor,
   1686  1.1  christos 				    eap_methods[i].method);
   1687  1.1  christos 		if (name) {
   1688  1.1  christos 			ret = os_snprintf(pos, end - pos, "%s%s",
   1689  1.1  christos 					  pos == buf ? "" : " ", name);
   1690  1.2  christos 			if (os_snprintf_error(end - pos, ret))
   1691  1.1  christos 				break;
   1692  1.1  christos 			pos += ret;
   1693  1.1  christos 		}
   1694  1.1  christos 	}
   1695  1.1  christos 
   1696  1.1  christos 	end[-1] = '\0';
   1697  1.1  christos 
   1698  1.1  christos 	return buf;
   1699  1.1  christos }
   1700  1.6  christos #endif /* NO_CONFIG_WRITE */
   1701  1.1  christos 
   1702  1.1  christos 
   1703  1.1  christos static int wpa_config_parse_password(const struct parse_data *data,
   1704  1.1  christos 				     struct wpa_ssid *ssid, int line,
   1705  1.1  christos 				     const char *value)
   1706  1.1  christos {
   1707  1.1  christos 	u8 *hash;
   1708  1.1  christos 
   1709  1.1  christos 	if (os_strcmp(value, "NULL") == 0) {
   1710  1.6  christos 		if (!ssid->eap.password)
   1711  1.6  christos 			return 1; /* Already unset */
   1712  1.1  christos 		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
   1713  1.2  christos 		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1714  1.1  christos 		ssid->eap.password = NULL;
   1715  1.1  christos 		ssid->eap.password_len = 0;
   1716  1.1  christos 		return 0;
   1717  1.1  christos 	}
   1718  1.1  christos 
   1719  1.2  christos #ifdef CONFIG_EXT_PASSWORD
   1720  1.2  christos 	if (os_strncmp(value, "ext:", 4) == 0) {
   1721  1.2  christos 		char *name = os_strdup(value + 4);
   1722  1.9  christos 		if (!name)
   1723  1.2  christos 			return -1;
   1724  1.2  christos 		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1725  1.2  christos 		ssid->eap.password = (u8 *) name;
   1726  1.2  christos 		ssid->eap.password_len = os_strlen(name);
   1727  1.2  christos 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1728  1.2  christos 		ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1729  1.2  christos 		return 0;
   1730  1.2  christos 	}
   1731  1.2  christos #endif /* CONFIG_EXT_PASSWORD */
   1732  1.2  christos 
   1733  1.1  christos 	if (os_strncmp(value, "hash:", 5) != 0) {
   1734  1.1  christos 		char *tmp;
   1735  1.1  christos 		size_t res_len;
   1736  1.1  christos 
   1737  1.1  christos 		tmp = wpa_config_parse_string(value, &res_len);
   1738  1.9  christos 		if (!tmp) {
   1739  1.9  christos 			wpa_printf(MSG_ERROR,
   1740  1.9  christos 				   "Line %d: failed to parse password.", line);
   1741  1.1  christos 			return -1;
   1742  1.1  christos 		}
   1743  1.1  christos 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
   1744  1.1  christos 				      (u8 *) tmp, res_len);
   1745  1.1  christos 
   1746  1.2  christos 		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1747  1.1  christos 		ssid->eap.password = (u8 *) tmp;
   1748  1.1  christos 		ssid->eap.password_len = res_len;
   1749  1.1  christos 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1750  1.2  christos 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1751  1.1  christos 
   1752  1.1  christos 		return 0;
   1753  1.1  christos 	}
   1754  1.1  christos 
   1755  1.1  christos 
   1756  1.1  christos 	/* NtPasswordHash: hash:<32 hex digits> */
   1757  1.1  christos 	if (os_strlen(value + 5) != 2 * 16) {
   1758  1.9  christos 		wpa_printf(MSG_ERROR,
   1759  1.9  christos 			   "Line %d: Invalid password hash length (expected 32 hex digits)",
   1760  1.9  christos 			   line);
   1761  1.1  christos 		return -1;
   1762  1.1  christos 	}
   1763  1.1  christos 
   1764  1.1  christos 	hash = os_malloc(16);
   1765  1.9  christos 	if (!hash)
   1766  1.1  christos 		return -1;
   1767  1.1  christos 
   1768  1.1  christos 	if (hexstr2bin(value + 5, hash, 16)) {
   1769  1.1  christos 		os_free(hash);
   1770  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
   1771  1.1  christos 		return -1;
   1772  1.1  christos 	}
   1773  1.1  christos 
   1774  1.1  christos 	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
   1775  1.1  christos 
   1776  1.6  christos 	if (ssid->eap.password && ssid->eap.password_len == 16 &&
   1777  1.6  christos 	    os_memcmp(ssid->eap.password, hash, 16) == 0 &&
   1778  1.6  christos 	    (ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
   1779  1.6  christos 		bin_clear_free(hash, 16);
   1780  1.6  christos 		return 1;
   1781  1.6  christos 	}
   1782  1.2  christos 	bin_clear_free(ssid->eap.password, ssid->eap.password_len);
   1783  1.1  christos 	ssid->eap.password = hash;
   1784  1.1  christos 	ssid->eap.password_len = 16;
   1785  1.1  christos 	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
   1786  1.2  christos 	ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
   1787  1.1  christos 
   1788  1.1  christos 	return 0;
   1789  1.1  christos }
   1790  1.1  christos 
   1791  1.1  christos 
   1792  1.9  christos static int wpa_config_parse_machine_password(const struct parse_data *data,
   1793  1.9  christos 					     struct wpa_ssid *ssid, int line,
   1794  1.9  christos 					     const char *value)
   1795  1.9  christos {
   1796  1.9  christos 	u8 *hash;
   1797  1.9  christos 
   1798  1.9  christos 	if (os_strcmp(value, "NULL") == 0) {
   1799  1.9  christos 		if (!ssid->eap.machine_password)
   1800  1.9  christos 			return 1; /* Already unset */
   1801  1.9  christos 		wpa_printf(MSG_DEBUG,
   1802  1.9  christos 			   "Unset configuration string 'machine_password'");
   1803  1.9  christos 		bin_clear_free(ssid->eap.machine_password,
   1804  1.9  christos 			       ssid->eap.machine_password_len);
   1805  1.9  christos 		ssid->eap.machine_password = NULL;
   1806  1.9  christos 		ssid->eap.machine_password_len = 0;
   1807  1.9  christos 		return 0;
   1808  1.9  christos 	}
   1809  1.9  christos 
   1810  1.9  christos #ifdef CONFIG_EXT_PASSWORD
   1811  1.9  christos 	if (os_strncmp(value, "ext:", 4) == 0) {
   1812  1.9  christos 		char *name = os_strdup(value + 4);
   1813  1.9  christos 
   1814  1.9  christos 		if (!name)
   1815  1.9  christos 			return -1;
   1816  1.9  christos 		bin_clear_free(ssid->eap.machine_password,
   1817  1.9  christos 			       ssid->eap.machine_password_len);
   1818  1.9  christos 		ssid->eap.machine_password = (u8 *) name;
   1819  1.9  christos 		ssid->eap.machine_password_len = os_strlen(name);
   1820  1.9  christos 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
   1821  1.9  christos 		ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
   1822  1.9  christos 		return 0;
   1823  1.9  christos 	}
   1824  1.9  christos #endif /* CONFIG_EXT_PASSWORD */
   1825  1.9  christos 
   1826  1.9  christos 	if (os_strncmp(value, "hash:", 5) != 0) {
   1827  1.9  christos 		char *tmp;
   1828  1.9  christos 		size_t res_len;
   1829  1.9  christos 
   1830  1.9  christos 		tmp = wpa_config_parse_string(value, &res_len);
   1831  1.9  christos 		if (!tmp) {
   1832  1.9  christos 			wpa_printf(MSG_ERROR,
   1833  1.9  christos 				   "Line %d: failed to parse machine_password.",
   1834  1.9  christos 				   line);
   1835  1.9  christos 			return -1;
   1836  1.9  christos 		}
   1837  1.9  christos 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
   1838  1.9  christos 				      (u8 *) tmp, res_len);
   1839  1.9  christos 
   1840  1.9  christos 		bin_clear_free(ssid->eap.machine_password,
   1841  1.9  christos 			       ssid->eap.machine_password_len);
   1842  1.9  christos 		ssid->eap.machine_password = (u8 *) tmp;
   1843  1.9  christos 		ssid->eap.machine_password_len = res_len;
   1844  1.9  christos 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
   1845  1.9  christos 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
   1846  1.9  christos 
   1847  1.9  christos 		return 0;
   1848  1.9  christos 	}
   1849  1.9  christos 
   1850  1.9  christos 
   1851  1.9  christos 	/* NtPasswordHash: hash:<32 hex digits> */
   1852  1.9  christos 	if (os_strlen(value + 5) != 2 * 16) {
   1853  1.9  christos 		wpa_printf(MSG_ERROR,
   1854  1.9  christos 			   "Line %d: Invalid machine_password hash length (expected 32 hex digits)",
   1855  1.9  christos 			   line);
   1856  1.9  christos 		return -1;
   1857  1.9  christos 	}
   1858  1.9  christos 
   1859  1.9  christos 	hash = os_malloc(16);
   1860  1.9  christos 	if (!hash)
   1861  1.9  christos 		return -1;
   1862  1.9  christos 
   1863  1.9  christos 	if (hexstr2bin(value + 5, hash, 16)) {
   1864  1.9  christos 		os_free(hash);
   1865  1.9  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid machine_password hash",
   1866  1.9  christos 			   line);
   1867  1.9  christos 		return -1;
   1868  1.9  christos 	}
   1869  1.9  christos 
   1870  1.9  christos 	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
   1871  1.9  christos 
   1872  1.9  christos 	if (ssid->eap.machine_password &&
   1873  1.9  christos 	    ssid->eap.machine_password_len == 16 &&
   1874  1.9  christos 	    os_memcmp(ssid->eap.machine_password, hash, 16) == 0 &&
   1875  1.9  christos 	    (ssid->eap.flags & EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH)) {
   1876  1.9  christos 		bin_clear_free(hash, 16);
   1877  1.9  christos 		return 1;
   1878  1.9  christos 	}
   1879  1.9  christos 	bin_clear_free(ssid->eap.machine_password,
   1880  1.9  christos 		       ssid->eap.machine_password_len);
   1881  1.9  christos 	ssid->eap.machine_password = hash;
   1882  1.9  christos 	ssid->eap.machine_password_len = 16;
   1883  1.9  christos 	ssid->eap.flags |= EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
   1884  1.9  christos 	ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
   1885  1.9  christos 
   1886  1.9  christos 	return 0;
   1887  1.9  christos }
   1888  1.9  christos 
   1889  1.9  christos 
   1890  1.6  christos #ifndef NO_CONFIG_WRITE
   1891  1.9  christos 
   1892  1.1  christos static char * wpa_config_write_password(const struct parse_data *data,
   1893  1.1  christos 					struct wpa_ssid *ssid)
   1894  1.1  christos {
   1895  1.1  christos 	char *buf;
   1896  1.1  christos 
   1897  1.9  christos 	if (!ssid->eap.password)
   1898  1.1  christos 		return NULL;
   1899  1.1  christos 
   1900  1.2  christos #ifdef CONFIG_EXT_PASSWORD
   1901  1.2  christos 	if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
   1902  1.2  christos 		buf = os_zalloc(4 + ssid->eap.password_len + 1);
   1903  1.9  christos 		if (!buf)
   1904  1.2  christos 			return NULL;
   1905  1.2  christos 		os_memcpy(buf, "ext:", 4);
   1906  1.2  christos 		os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
   1907  1.2  christos 		return buf;
   1908  1.2  christos 	}
   1909  1.2  christos #endif /* CONFIG_EXT_PASSWORD */
   1910  1.2  christos 
   1911  1.1  christos 	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
   1912  1.1  christos 		return wpa_config_write_string(
   1913  1.1  christos 			ssid->eap.password, ssid->eap.password_len);
   1914  1.1  christos 	}
   1915  1.1  christos 
   1916  1.1  christos 	buf = os_malloc(5 + 32 + 1);
   1917  1.9  christos 	if (!buf)
   1918  1.1  christos 		return NULL;
   1919  1.1  christos 
   1920  1.1  christos 	os_memcpy(buf, "hash:", 5);
   1921  1.1  christos 	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
   1922  1.1  christos 
   1923  1.1  christos 	return buf;
   1924  1.1  christos }
   1925  1.9  christos 
   1926  1.9  christos 
   1927  1.9  christos static char * wpa_config_write_machine_password(const struct parse_data *data,
   1928  1.9  christos 						struct wpa_ssid *ssid)
   1929  1.9  christos {
   1930  1.9  christos 	char *buf;
   1931  1.9  christos 
   1932  1.9  christos 	if (!ssid->eap.machine_password)
   1933  1.9  christos 		return NULL;
   1934  1.9  christos 
   1935  1.9  christos #ifdef CONFIG_EXT_PASSWORD
   1936  1.9  christos 	if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD) {
   1937  1.9  christos 		buf = os_zalloc(4 + ssid->eap.machine_password_len + 1);
   1938  1.9  christos 		if (!buf)
   1939  1.9  christos 			return NULL;
   1940  1.9  christos 		os_memcpy(buf, "ext:", 4);
   1941  1.9  christos 		os_memcpy(buf + 4, ssid->eap.machine_password,
   1942  1.9  christos 			  ssid->eap.machine_password_len);
   1943  1.9  christos 		return buf;
   1944  1.9  christos 	}
   1945  1.9  christos #endif /* CONFIG_EXT_PASSWORD */
   1946  1.9  christos 
   1947  1.9  christos 	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH)) {
   1948  1.9  christos 		return wpa_config_write_string(
   1949  1.9  christos 			ssid->eap.machine_password,
   1950  1.9  christos 			ssid->eap.machine_password_len);
   1951  1.9  christos 	}
   1952  1.9  christos 
   1953  1.9  christos 	buf = os_malloc(5 + 32 + 1);
   1954  1.9  christos 	if (!buf)
   1955  1.9  christos 		return NULL;
   1956  1.9  christos 
   1957  1.9  christos 	os_memcpy(buf, "hash:", 5);
   1958  1.9  christos 	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.machine_password, 16);
   1959  1.9  christos 
   1960  1.9  christos 	return buf;
   1961  1.9  christos }
   1962  1.9  christos 
   1963  1.6  christos #endif /* NO_CONFIG_WRITE */
   1964  1.1  christos #endif /* IEEE8021X_EAPOL */
   1965  1.1  christos 
   1966  1.1  christos 
   1967  1.9  christos #ifdef CONFIG_WEP
   1968  1.9  christos 
   1969  1.1  christos static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
   1970  1.1  christos 				    const char *value, int idx)
   1971  1.1  christos {
   1972  1.1  christos 	char *buf, title[20];
   1973  1.1  christos 	int res;
   1974  1.1  christos 
   1975  1.1  christos 	buf = wpa_config_parse_string(value, len);
   1976  1.1  christos 	if (buf == NULL) {
   1977  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
   1978  1.1  christos 			   line, idx, value);
   1979  1.1  christos 		return -1;
   1980  1.1  christos 	}
   1981  1.1  christos 	if (*len > MAX_WEP_KEY_LEN) {
   1982  1.1  christos 		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
   1983  1.1  christos 			   line, idx, value);
   1984  1.1  christos 		os_free(buf);
   1985  1.1  christos 		return -1;
   1986  1.1  christos 	}
   1987  1.2  christos 	if (*len && *len != 5 && *len != 13 && *len != 16) {
   1988  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - "
   1989  1.2  christos 			   "this network block will be ignored",
   1990  1.2  christos 			   line, (unsigned int) *len);
   1991  1.2  christos 	}
   1992  1.1  christos 	os_memcpy(key, buf, *len);
   1993  1.2  christos 	str_clear_free(buf);
   1994  1.1  christos 	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
   1995  1.2  christos 	if (!os_snprintf_error(sizeof(title), res))
   1996  1.1  christos 		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
   1997  1.1  christos 	return 0;
   1998  1.1  christos }
   1999  1.1  christos 
   2000  1.1  christos 
   2001  1.1  christos static int wpa_config_parse_wep_key0(const struct parse_data *data,
   2002  1.1  christos 				     struct wpa_ssid *ssid, int line,
   2003  1.1  christos 				     const char *value)
   2004  1.1  christos {
   2005  1.1  christos 	return wpa_config_parse_wep_key(ssid->wep_key[0],
   2006  1.1  christos 					&ssid->wep_key_len[0], line,
   2007  1.1  christos 					value, 0);
   2008  1.1  christos }
   2009  1.1  christos 
   2010  1.1  christos 
   2011  1.1  christos static int wpa_config_parse_wep_key1(const struct parse_data *data,
   2012  1.1  christos 				     struct wpa_ssid *ssid, int line,
   2013  1.1  christos 				     const char *value)
   2014  1.1  christos {
   2015  1.1  christos 	return wpa_config_parse_wep_key(ssid->wep_key[1],
   2016  1.1  christos 					&ssid->wep_key_len[1], line,
   2017  1.1  christos 					value, 1);
   2018  1.1  christos }
   2019  1.1  christos 
   2020  1.1  christos 
   2021  1.1  christos static int wpa_config_parse_wep_key2(const struct parse_data *data,
   2022  1.1  christos 				     struct wpa_ssid *ssid, int line,
   2023  1.1  christos 				     const char *value)
   2024  1.1  christos {
   2025  1.1  christos 	return wpa_config_parse_wep_key(ssid->wep_key[2],
   2026  1.1  christos 					&ssid->wep_key_len[2], line,
   2027  1.1  christos 					value, 2);
   2028  1.1  christos }
   2029  1.1  christos 
   2030  1.1  christos 
   2031  1.1  christos static int wpa_config_parse_wep_key3(const struct parse_data *data,
   2032  1.1  christos 				     struct wpa_ssid *ssid, int line,
   2033  1.1  christos 				     const char *value)
   2034  1.1  christos {
   2035  1.1  christos 	return wpa_config_parse_wep_key(ssid->wep_key[3],
   2036  1.1  christos 					&ssid->wep_key_len[3], line,
   2037  1.1  christos 					value, 3);
   2038  1.1  christos }
   2039  1.1  christos 
   2040  1.1  christos 
   2041  1.1  christos #ifndef NO_CONFIG_WRITE
   2042  1.1  christos static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
   2043  1.1  christos {
   2044  1.1  christos 	if (ssid->wep_key_len[idx] == 0)
   2045  1.1  christos 		return NULL;
   2046  1.1  christos 	return wpa_config_write_string(ssid->wep_key[idx],
   2047  1.1  christos 				       ssid->wep_key_len[idx]);
   2048  1.1  christos }
   2049  1.1  christos 
   2050  1.1  christos 
   2051  1.1  christos static char * wpa_config_write_wep_key0(const struct parse_data *data,
   2052  1.1  christos 					struct wpa_ssid *ssid)
   2053  1.1  christos {
   2054  1.1  christos 	return wpa_config_write_wep_key(ssid, 0);
   2055  1.1  christos }
   2056  1.1  christos 
   2057  1.1  christos 
   2058  1.1  christos static char * wpa_config_write_wep_key1(const struct parse_data *data,
   2059  1.1  christos 					struct wpa_ssid *ssid)
   2060  1.1  christos {
   2061  1.1  christos 	return wpa_config_write_wep_key(ssid, 1);
   2062  1.1  christos }
   2063  1.1  christos 
   2064  1.1  christos 
   2065  1.1  christos static char * wpa_config_write_wep_key2(const struct parse_data *data,
   2066  1.1  christos 					struct wpa_ssid *ssid)
   2067  1.1  christos {
   2068  1.1  christos 	return wpa_config_write_wep_key(ssid, 2);
   2069  1.1  christos }
   2070  1.1  christos 
   2071  1.1  christos 
   2072  1.1  christos static char * wpa_config_write_wep_key3(const struct parse_data *data,
   2073  1.1  christos 					struct wpa_ssid *ssid)
   2074  1.1  christos {
   2075  1.1  christos 	return wpa_config_write_wep_key(ssid, 3);
   2076  1.1  christos }
   2077  1.1  christos #endif /* NO_CONFIG_WRITE */
   2078  1.1  christos 
   2079  1.9  christos #endif /* CONFIG_WEP */
   2080  1.9  christos 
   2081  1.1  christos 
   2082  1.2  christos #ifdef CONFIG_P2P
   2083  1.2  christos 
   2084  1.2  christos static int wpa_config_parse_go_p2p_dev_addr(const struct parse_data *data,
   2085  1.2  christos 					    struct wpa_ssid *ssid, int line,
   2086  1.2  christos 					    const char *value)
   2087  1.2  christos {
   2088  1.2  christos 	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
   2089  1.2  christos 	    os_strcmp(value, "any") == 0) {
   2090  1.2  christos 		os_memset(ssid->go_p2p_dev_addr, 0, ETH_ALEN);
   2091  1.2  christos 		wpa_printf(MSG_MSGDUMP, "GO P2P Device Address any");
   2092  1.2  christos 		return 0;
   2093  1.2  christos 	}
   2094  1.2  christos 	if (hwaddr_aton(value, ssid->go_p2p_dev_addr)) {
   2095  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid GO P2P Device Address '%s'.",
   2096  1.2  christos 			   line, value);
   2097  1.2  christos 		return -1;
   2098  1.2  christos 	}
   2099  1.2  christos 	ssid->bssid_set = 1;
   2100  1.2  christos 	wpa_printf(MSG_MSGDUMP, "GO P2P Device Address " MACSTR,
   2101  1.2  christos 		   MAC2STR(ssid->go_p2p_dev_addr));
   2102  1.2  christos 	return 0;
   2103  1.2  christos }
   2104  1.2  christos 
   2105  1.2  christos 
   2106  1.2  christos #ifndef NO_CONFIG_WRITE
   2107  1.2  christos static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data,
   2108  1.2  christos 					       struct wpa_ssid *ssid)
   2109  1.2  christos {
   2110  1.2  christos 	char *value;
   2111  1.2  christos 	int res;
   2112  1.2  christos 
   2113  1.2  christos 	if (is_zero_ether_addr(ssid->go_p2p_dev_addr))
   2114  1.2  christos 		return NULL;
   2115  1.2  christos 
   2116  1.2  christos 	value = os_malloc(20);
   2117  1.2  christos 	if (value == NULL)
   2118  1.2  christos 		return NULL;
   2119  1.2  christos 	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr));
   2120  1.2  christos 	if (os_snprintf_error(20, res)) {
   2121  1.2  christos 		os_free(value);
   2122  1.2  christos 		return NULL;
   2123  1.2  christos 	}
   2124  1.2  christos 	value[20 - 1] = '\0';
   2125  1.2  christos 	return value;
   2126  1.2  christos }
   2127  1.2  christos #endif /* NO_CONFIG_WRITE */
   2128  1.2  christos 
   2129  1.2  christos 
   2130  1.2  christos static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
   2131  1.2  christos 					    struct wpa_ssid *ssid, int line,
   2132  1.2  christos 					    const char *value)
   2133  1.2  christos {
   2134  1.2  christos 	return wpa_config_parse_addr_list(data, line, value,
   2135  1.2  christos 					  &ssid->p2p_client_list,
   2136  1.2  christos 					  &ssid->num_p2p_clients,
   2137  1.2  christos 					  "p2p_client_list", 0, 0);
   2138  1.2  christos }
   2139  1.2  christos 
   2140  1.2  christos 
   2141  1.2  christos #ifndef NO_CONFIG_WRITE
   2142  1.2  christos static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
   2143  1.2  christos 					       struct wpa_ssid *ssid)
   2144  1.2  christos {
   2145  1.2  christos 	return wpa_config_write_addr_list(data, ssid->p2p_client_list,
   2146  1.2  christos 					  ssid->num_p2p_clients,
   2147  1.2  christos 					  "p2p_client_list");
   2148  1.2  christos }
   2149  1.2  christos #endif /* NO_CONFIG_WRITE */
   2150  1.2  christos 
   2151  1.2  christos 
   2152  1.2  christos static int wpa_config_parse_psk_list(const struct parse_data *data,
   2153  1.2  christos 				     struct wpa_ssid *ssid, int line,
   2154  1.2  christos 				     const char *value)
   2155  1.2  christos {
   2156  1.2  christos 	struct psk_list_entry *p;
   2157  1.2  christos 	const char *pos;
   2158  1.2  christos 
   2159  1.2  christos 	p = os_zalloc(sizeof(*p));
   2160  1.2  christos 	if (p == NULL)
   2161  1.2  christos 		return -1;
   2162  1.2  christos 
   2163  1.2  christos 	pos = value;
   2164  1.2  christos 	if (os_strncmp(pos, "P2P-", 4) == 0) {
   2165  1.2  christos 		p->p2p = 1;
   2166  1.2  christos 		pos += 4;
   2167  1.2  christos 	}
   2168  1.2  christos 
   2169  1.2  christos 	if (hwaddr_aton(pos, p->addr)) {
   2170  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'",
   2171  1.2  christos 			   line, pos);
   2172  1.2  christos 		os_free(p);
   2173  1.2  christos 		return -1;
   2174  1.2  christos 	}
   2175  1.2  christos 	pos += 17;
   2176  1.2  christos 	if (*pos != '-') {
   2177  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'",
   2178  1.2  christos 			   line, pos);
   2179  1.2  christos 		os_free(p);
   2180  1.2  christos 		return -1;
   2181  1.2  christos 	}
   2182  1.2  christos 	pos++;
   2183  1.2  christos 
   2184  1.2  christos 	if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') {
   2185  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'",
   2186  1.2  christos 			   line, pos);
   2187  1.2  christos 		os_free(p);
   2188  1.2  christos 		return -1;
   2189  1.2  christos 	}
   2190  1.2  christos 
   2191  1.2  christos 	dl_list_add(&ssid->psk_list, &p->list);
   2192  1.2  christos 
   2193  1.2  christos 	return 0;
   2194  1.2  christos }
   2195  1.2  christos 
   2196  1.2  christos 
   2197  1.2  christos #ifndef NO_CONFIG_WRITE
   2198  1.2  christos static char * wpa_config_write_psk_list(const struct parse_data *data,
   2199  1.2  christos 					struct wpa_ssid *ssid)
   2200  1.2  christos {
   2201  1.2  christos 	return NULL;
   2202  1.2  christos }
   2203  1.2  christos #endif /* NO_CONFIG_WRITE */
   2204  1.2  christos 
   2205  1.2  christos #endif /* CONFIG_P2P */
   2206  1.2  christos 
   2207  1.2  christos 
   2208  1.2  christos #ifdef CONFIG_MESH
   2209  1.2  christos 
   2210  1.2  christos static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data,
   2211  1.2  christos 					     struct wpa_ssid *ssid, int line,
   2212  1.2  christos 					     const char *value)
   2213  1.2  christos {
   2214  1.2  christos 	int *rates = wpa_config_parse_int_array(value);
   2215  1.2  christos 
   2216  1.2  christos 	if (rates == NULL) {
   2217  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'",
   2218  1.2  christos 			   line, value);
   2219  1.2  christos 		return -1;
   2220  1.2  christos 	}
   2221  1.2  christos 	if (rates[0] == 0) {
   2222  1.2  christos 		os_free(rates);
   2223  1.2  christos 		rates = NULL;
   2224  1.2  christos 	}
   2225  1.2  christos 
   2226  1.2  christos 	os_free(ssid->mesh_basic_rates);
   2227  1.2  christos 	ssid->mesh_basic_rates = rates;
   2228  1.2  christos 
   2229  1.2  christos 	return 0;
   2230  1.2  christos }
   2231  1.2  christos 
   2232  1.2  christos 
   2233  1.2  christos #ifndef NO_CONFIG_WRITE
   2234  1.2  christos 
   2235  1.2  christos static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
   2236  1.2  christos 						struct wpa_ssid *ssid)
   2237  1.2  christos {
   2238  1.2  christos 	return wpa_config_write_freqs(data, ssid->mesh_basic_rates);
   2239  1.2  christos }
   2240  1.2  christos 
   2241  1.2  christos #endif /* NO_CONFIG_WRITE */
   2242  1.2  christos 
   2243  1.2  christos #endif /* CONFIG_MESH */
   2244  1.2  christos 
   2245  1.2  christos 
   2246  1.7  christos #ifdef CONFIG_MACSEC
   2247  1.7  christos 
   2248  1.7  christos static int wpa_config_parse_mka_cak(const struct parse_data *data,
   2249  1.7  christos 				    struct wpa_ssid *ssid, int line,
   2250  1.7  christos 				    const char *value)
   2251  1.7  christos {
   2252  1.8  christos 	size_t len;
   2253  1.8  christos 
   2254  1.8  christos 	len = os_strlen(value);
   2255  1.8  christos 	if (len > 2 * MACSEC_CAK_MAX_LEN ||
   2256  1.8  christos 	    (len != 2 * 16 && len != 2 * 32) ||
   2257  1.8  christos 	    hexstr2bin(value, ssid->mka_cak, len / 2)) {
   2258  1.7  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
   2259  1.7  christos 			   line, value);
   2260  1.7  christos 		return -1;
   2261  1.7  christos 	}
   2262  1.8  christos 	ssid->mka_cak_len = len / 2;
   2263  1.7  christos 	ssid->mka_psk_set |= MKA_PSK_SET_CAK;
   2264  1.7  christos 
   2265  1.8  christos 	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak,
   2266  1.8  christos 			ssid->mka_cak_len);
   2267  1.7  christos 	return 0;
   2268  1.7  christos }
   2269  1.7  christos 
   2270  1.7  christos 
   2271  1.7  christos static int wpa_config_parse_mka_ckn(const struct parse_data *data,
   2272  1.7  christos 				    struct wpa_ssid *ssid, int line,
   2273  1.7  christos 				    const char *value)
   2274  1.7  christos {
   2275  1.8  christos 	size_t len;
   2276  1.8  christos 
   2277  1.8  christos 	len = os_strlen(value);
   2278  1.8  christos 	if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
   2279  1.8  christos 	    len < 2 || /* too short */
   2280  1.8  christos 	    len % 2 != 0 /* not an integral number of bytes */) {
   2281  1.8  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
   2282  1.8  christos 			   line, value);
   2283  1.8  christos 		return -1;
   2284  1.8  christos 	}
   2285  1.8  christos 	ssid->mka_ckn_len = len / 2;
   2286  1.8  christos 	if (hexstr2bin(value, ssid->mka_ckn, ssid->mka_ckn_len)) {
   2287  1.7  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
   2288  1.7  christos 			   line, value);
   2289  1.7  christos 		return -1;
   2290  1.7  christos 	}
   2291  1.7  christos 
   2292  1.7  christos 	ssid->mka_psk_set |= MKA_PSK_SET_CKN;
   2293  1.7  christos 
   2294  1.8  christos 	wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn,
   2295  1.8  christos 			ssid->mka_ckn_len);
   2296  1.7  christos 	return 0;
   2297  1.7  christos }
   2298  1.7  christos 
   2299  1.7  christos 
   2300  1.7  christos #ifndef NO_CONFIG_WRITE
   2301  1.7  christos 
   2302  1.7  christos static char * wpa_config_write_mka_cak(const struct parse_data *data,
   2303  1.7  christos 				       struct wpa_ssid *ssid)
   2304  1.7  christos {
   2305  1.7  christos 	if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
   2306  1.7  christos 		return NULL;
   2307  1.7  christos 
   2308  1.8  christos 	return wpa_config_write_string_hex(ssid->mka_cak, ssid->mka_cak_len);
   2309  1.7  christos }
   2310  1.7  christos 
   2311  1.7  christos 
   2312  1.7  christos static char * wpa_config_write_mka_ckn(const struct parse_data *data,
   2313  1.7  christos 				       struct wpa_ssid *ssid)
   2314  1.7  christos {
   2315  1.7  christos 	if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
   2316  1.7  christos 		return NULL;
   2317  1.8  christos 	return wpa_config_write_string_hex(ssid->mka_ckn, ssid->mka_ckn_len);
   2318  1.7  christos }
   2319  1.7  christos 
   2320  1.7  christos #endif /* NO_CONFIG_WRITE */
   2321  1.7  christos 
   2322  1.7  christos #endif /* CONFIG_MACSEC */
   2323  1.7  christos 
   2324  1.7  christos 
   2325  1.8  christos #ifdef CONFIG_OCV
   2326  1.8  christos 
   2327  1.8  christos static int wpa_config_parse_ocv(const struct parse_data *data,
   2328  1.8  christos 				struct wpa_ssid *ssid, int line,
   2329  1.8  christos 				const char *value)
   2330  1.8  christos {
   2331  1.8  christos 	char *end;
   2332  1.8  christos 
   2333  1.8  christos 	ssid->ocv = strtol(value, &end, 0);
   2334  1.8  christos 	if (*end || ssid->ocv < 0 || ssid->ocv > 1) {
   2335  1.8  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid ocv value '%s'.",
   2336  1.8  christos 			   line, value);
   2337  1.8  christos 		return -1;
   2338  1.8  christos 	}
   2339  1.8  christos 	if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION)
   2340  1.8  christos 		ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
   2341  1.8  christos 	return 0;
   2342  1.8  christos }
   2343  1.8  christos 
   2344  1.8  christos 
   2345  1.8  christos #ifndef NO_CONFIG_WRITE
   2346  1.8  christos static char * wpa_config_write_ocv(const struct parse_data *data,
   2347  1.8  christos 				   struct wpa_ssid *ssid)
   2348  1.8  christos {
   2349  1.8  christos 	char *value = os_malloc(20);
   2350  1.8  christos 
   2351  1.8  christos 	if (!value)
   2352  1.8  christos 		return NULL;
   2353  1.8  christos 	os_snprintf(value, 20, "%d", ssid->ocv);
   2354  1.8  christos 	value[20 - 1] = '\0';
   2355  1.8  christos 	return value;
   2356  1.8  christos }
   2357  1.8  christos #endif /* NO_CONFIG_WRITE */
   2358  1.8  christos 
   2359  1.8  christos #endif /* CONFIG_OCV */
   2360  1.8  christos 
   2361  1.8  christos 
   2362  1.7  christos static int wpa_config_parse_peerkey(const struct parse_data *data,
   2363  1.7  christos 				    struct wpa_ssid *ssid, int line,
   2364  1.7  christos 				    const char *value)
   2365  1.7  christos {
   2366  1.7  christos 	wpa_printf(MSG_INFO, "NOTE: Obsolete peerkey parameter ignored");
   2367  1.7  christos 	return 0;
   2368  1.7  christos }
   2369  1.7  christos 
   2370  1.7  christos 
   2371  1.7  christos #ifndef NO_CONFIG_WRITE
   2372  1.7  christos static char * wpa_config_write_peerkey(const struct parse_data *data,
   2373  1.7  christos 				       struct wpa_ssid *ssid)
   2374  1.7  christos {
   2375  1.7  christos 	return NULL;
   2376  1.7  christos }
   2377  1.7  christos #endif /* NO_CONFIG_WRITE */
   2378  1.7  christos 
   2379  1.7  christos 
   2380  1.9  christos static int wpa_config_parse_mac_value(const struct parse_data *data,
   2381  1.9  christos 				      struct wpa_ssid *ssid, int line,
   2382  1.9  christos 				      const char *value)
   2383  1.9  christos {
   2384  1.9  christos 	u8 mac_value[ETH_ALEN];
   2385  1.9  christos 
   2386  1.9  christos 	if (hwaddr_aton(value, mac_value) == 0) {
   2387  1.9  christos 		if (ether_addr_equal(mac_value, ssid->mac_value))
   2388  1.9  christos 			return 1;
   2389  1.9  christos 		os_memcpy(ssid->mac_value, mac_value, ETH_ALEN);
   2390  1.9  christos 		return 0;
   2391  1.9  christos 	}
   2392  1.9  christos 
   2393  1.9  christos 	wpa_printf(MSG_ERROR, "Line %d: Invalid MAC address '%s'",
   2394  1.9  christos 		   line, value);
   2395  1.9  christos 	return -1;
   2396  1.9  christos }
   2397  1.9  christos 
   2398  1.9  christos 
   2399  1.9  christos #ifndef NO_CONFIG_WRITE
   2400  1.9  christos static char * wpa_config_write_mac_value(const struct parse_data *data,
   2401  1.9  christos 					 struct wpa_ssid *ssid)
   2402  1.9  christos {
   2403  1.9  christos 	const size_t size = 3 * ETH_ALEN;
   2404  1.9  christos 	char *value;
   2405  1.9  christos 	int res;
   2406  1.9  christos 
   2407  1.9  christos 	if (ssid->mac_addr != WPAS_MAC_ADDR_STYLE_DEDICATED_PER_ESS)
   2408  1.9  christos 		return NULL;
   2409  1.9  christos 
   2410  1.9  christos 	value = os_malloc(size);
   2411  1.9  christos 	if (!value)
   2412  1.9  christos 		return NULL;
   2413  1.9  christos 	res = os_snprintf(value, size, MACSTR, MAC2STR(ssid->mac_value));
   2414  1.9  christos 	if (os_snprintf_error(size, res)) {
   2415  1.9  christos 		os_free(value);
   2416  1.9  christos 		return NULL;
   2417  1.9  christos 	}
   2418  1.9  christos 	value[size - 1] = '\0';
   2419  1.9  christos 	return value;
   2420  1.9  christos }
   2421  1.9  christos #endif /* NO_CONFIG_WRITE */
   2422  1.9  christos 
   2423  1.9  christos 
   2424  1.2  christos /* Helper macros for network block parser */
   2425  1.1  christos 
   2426  1.1  christos #ifdef OFFSET
   2427  1.1  christos #undef OFFSET
   2428  1.1  christos #endif /* OFFSET */
   2429  1.1  christos /* OFFSET: Get offset of a variable within the wpa_ssid structure */
   2430  1.1  christos #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
   2431  1.1  christos 
   2432  1.1  christos /* STR: Define a string variable for an ASCII string; f = field name */
   2433  1.1  christos #ifdef NO_CONFIG_WRITE
   2434  1.1  christos #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
   2435  1.9  christos #define _STRe(f, m) #f, wpa_config_parse_str, OFFSET(eap.m)
   2436  1.1  christos #else /* NO_CONFIG_WRITE */
   2437  1.1  christos #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
   2438  1.9  christos #define _STRe(f, m) #f, wpa_config_parse_str, wpa_config_write_str, \
   2439  1.9  christos 		OFFSET(eap.m)
   2440  1.1  christos #endif /* NO_CONFIG_WRITE */
   2441  1.1  christos #define STR(f) _STR(f), NULL, NULL, NULL, 0
   2442  1.9  christos #define STRe(f, m) _STRe(f, m), NULL, NULL, NULL, 0
   2443  1.1  christos #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
   2444  1.9  christos #define STR_KEYe(f, m) _STRe(f, m), NULL, NULL, NULL, 1
   2445  1.1  christos 
   2446  1.1  christos /* STR_LEN: Define a string variable with a separate variable for storing the
   2447  1.1  christos  * data length. Unlike STR(), this can be used to store arbitrary binary data
   2448  1.1  christos  * (i.e., even nul termination character). */
   2449  1.1  christos #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
   2450  1.9  christos #define _STR_LENe(f, m) _STRe(f, m), OFFSET(eap.m ## _len)
   2451  1.1  christos #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
   2452  1.9  christos #define STR_LENe(f, m) _STR_LENe(f, m), NULL, NULL, 0
   2453  1.1  christos #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
   2454  1.1  christos 
   2455  1.1  christos /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
   2456  1.1  christos  * explicitly specified. */
   2457  1.1  christos #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
   2458  1.1  christos #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
   2459  1.1  christos #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
   2460  1.1  christos 
   2461  1.1  christos #ifdef NO_CONFIG_WRITE
   2462  1.1  christos #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
   2463  1.9  christos #define _INTe(f, m) #f, wpa_config_parse_int, OFFSET(eap.m), (void *) 0
   2464  1.1  christos #else /* NO_CONFIG_WRITE */
   2465  1.1  christos #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
   2466  1.1  christos 	OFFSET(f), (void *) 0
   2467  1.9  christos #define _INTe(f, m) #f, wpa_config_parse_int, wpa_config_write_int,	\
   2468  1.9  christos 	OFFSET(eap.m), (void *) 0
   2469  1.1  christos #endif /* NO_CONFIG_WRITE */
   2470  1.1  christos 
   2471  1.1  christos /* INT: Define an integer variable */
   2472  1.1  christos #define INT(f) _INT(f), NULL, NULL, 0
   2473  1.9  christos #define INTe(f, m) _INTe(f, m), NULL, NULL, 0
   2474  1.1  christos 
   2475  1.1  christos /* INT_RANGE: Define an integer variable with allowed value range */
   2476  1.9  christos #ifdef NO_CONFIG_WRITE
   2477  1.9  christos #define INT_RANGE(f, min, max) #f, wpa_config_parse_int_range, OFFSET(f), \
   2478  1.9  christos 	(void *) 0, (void *) (min), (void *) (max), 0
   2479  1.9  christos #else /* NO_CONFIG_WRITE */
   2480  1.9  christos #define INT_RANGE(f, min, max) #f, wpa_config_parse_int_range, \
   2481  1.9  christos 	wpa_config_write_int, OFFSET(f),	       \
   2482  1.9  christos 	(void *) 0, (void *) (min), (void *) (max), 0
   2483  1.9  christos #endif /* NO_CONFIG_WRITE */
   2484  1.1  christos 
   2485  1.1  christos /* FUNC: Define a configuration variable that uses a custom function for
   2486  1.1  christos  * parsing and writing the value. */
   2487  1.1  christos #ifdef NO_CONFIG_WRITE
   2488  1.1  christos #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
   2489  1.1  christos #else /* NO_CONFIG_WRITE */
   2490  1.1  christos #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
   2491  1.1  christos 	NULL, NULL, NULL, NULL
   2492  1.1  christos #endif /* NO_CONFIG_WRITE */
   2493  1.1  christos #define FUNC(f) _FUNC(f), 0
   2494  1.1  christos #define FUNC_KEY(f) _FUNC(f), 1
   2495  1.1  christos 
   2496  1.1  christos /*
   2497  1.1  christos  * Table of network configuration variables. This table is used to parse each
   2498  1.1  christos  * network configuration variable, e.g., each line in wpa_supplicant.conf file
   2499  1.1  christos  * that is inside a network block.
   2500  1.1  christos  *
   2501  1.1  christos  * This table is generated using the helper macros defined above and with
   2502  1.1  christos  * generous help from the C pre-processor. The field name is stored as a string
   2503  1.1  christos  * into .name and for STR and INT types, the offset of the target buffer within
   2504  1.1  christos  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
   2505  1.1  christos  * offset to the field containing the length of the configuration variable.
   2506  1.1  christos  * .param3 and .param4 can be used to mark the allowed range (length for STR
   2507  1.1  christos  * and value for INT).
   2508  1.1  christos  *
   2509  1.1  christos  * For each configuration line in wpa_supplicant.conf, the parser goes through
   2510  1.1  christos  * this table and select the entry that matches with the field name. The parser
   2511  1.1  christos  * function (.parser) is then called to parse the actual value of the field.
   2512  1.1  christos  *
   2513  1.1  christos  * This kind of mechanism makes it easy to add new configuration parameters,
   2514  1.1  christos  * since only one line needs to be added into this table and into the
   2515  1.1  christos  * struct wpa_ssid definition if the new variable is either a string or
   2516  1.1  christos  * integer. More complex types will need to use their own parser and writer
   2517  1.1  christos  * functions.
   2518  1.1  christos  */
   2519  1.1  christos static const struct parse_data ssid_fields[] = {
   2520  1.6  christos 	{ STR_RANGE(ssid, 0, SSID_MAX_LEN) },
   2521  1.1  christos 	{ INT_RANGE(scan_ssid, 0, 1) },
   2522  1.1  christos 	{ FUNC(bssid) },
   2523  1.7  christos 	{ FUNC(bssid_hint) },
   2524  1.9  christos 	{ FUNC(bssid_ignore) },
   2525  1.9  christos 	{ FUNC(bssid_accept) },
   2526  1.9  christos 	{ FUNC(bssid_blacklist) }, /* deprecated alias for bssid_ignore */
   2527  1.9  christos 	{ FUNC(bssid_whitelist) }, /* deprecated alias for bssid_accept */
   2528  1.1  christos 	{ FUNC_KEY(psk) },
   2529  1.6  christos 	{ INT(mem_only_psk) },
   2530  1.7  christos 	{ STR_KEY(sae_password) },
   2531  1.7  christos 	{ STR(sae_password_id) },
   2532  1.1  christos 	{ FUNC(proto) },
   2533  1.1  christos 	{ FUNC(key_mgmt) },
   2534  1.2  christos 	{ INT(bg_scan_period) },
   2535  1.1  christos 	{ FUNC(pairwise) },
   2536  1.1  christos 	{ FUNC(group) },
   2537  1.7  christos 	{ FUNC(group_mgmt) },
   2538  1.1  christos 	{ FUNC(auth_alg) },
   2539  1.1  christos 	{ FUNC(scan_freq) },
   2540  1.1  christos 	{ FUNC(freq_list) },
   2541  1.7  christos 	{ INT_RANGE(ht, 0, 1) },
   2542  1.7  christos 	{ INT_RANGE(vht, 0, 1) },
   2543  1.9  christos 	{ INT_RANGE(he, 0, 1) },
   2544  1.7  christos 	{ INT_RANGE(ht40, -1, 1) },
   2545  1.9  christos 	{ INT_RANGE(max_oper_chwidth, CONF_OPER_CHWIDTH_USE_HT,
   2546  1.9  christos 		    CONF_OPER_CHWIDTH_80P80MHZ) },
   2547  1.7  christos 	{ INT(vht_center_freq1) },
   2548  1.7  christos 	{ INT(vht_center_freq2) },
   2549  1.1  christos #ifdef IEEE8021X_EAPOL
   2550  1.1  christos 	{ FUNC(eap) },
   2551  1.9  christos 	{ STR_LENe(identity, identity) },
   2552  1.9  christos 	{ STR_LENe(anonymous_identity, anonymous_identity) },
   2553  1.9  christos 	{ STR_LENe(imsi_identity, imsi_identity) },
   2554  1.9  christos 	{ STR_LENe(machine_identity, machine_identity) },
   2555  1.1  christos 	{ FUNC_KEY(password) },
   2556  1.9  christos 	{ FUNC_KEY(machine_password) },
   2557  1.9  christos 	{ STRe(ca_cert, cert.ca_cert) },
   2558  1.9  christos 	{ STRe(ca_path, cert.ca_path) },
   2559  1.9  christos 	{ STRe(client_cert, cert.client_cert) },
   2560  1.9  christos 	{ STRe(private_key, cert.private_key) },
   2561  1.9  christos 	{ STR_KEYe(private_key_passwd, cert.private_key_passwd) },
   2562  1.9  christos 	{ STRe(subject_match, cert.subject_match) },
   2563  1.9  christos 	{ STRe(check_cert_subject, cert.check_cert_subject) },
   2564  1.9  christos 	{ STRe(altsubject_match, cert.altsubject_match) },
   2565  1.9  christos 	{ STRe(domain_suffix_match, cert.domain_suffix_match) },
   2566  1.9  christos 	{ STRe(domain_match, cert.domain_match) },
   2567  1.9  christos 	{ STRe(ca_cert2, phase2_cert.ca_cert) },
   2568  1.9  christos 	{ STRe(ca_path2, phase2_cert.ca_path) },
   2569  1.9  christos 	{ STRe(client_cert2, phase2_cert.client_cert) },
   2570  1.9  christos 	{ STRe(private_key2, phase2_cert.private_key) },
   2571  1.9  christos 	{ STR_KEYe(private_key2_passwd, phase2_cert.private_key_passwd) },
   2572  1.9  christos 	{ STRe(subject_match2, phase2_cert.subject_match) },
   2573  1.9  christos 	{ STRe(check_cert_subject2, phase2_cert.check_cert_subject) },
   2574  1.9  christos 	{ STRe(altsubject_match2, phase2_cert.altsubject_match) },
   2575  1.9  christos 	{ STRe(domain_suffix_match2, phase2_cert.domain_suffix_match) },
   2576  1.9  christos 	{ STRe(domain_match2, phase2_cert.domain_match) },
   2577  1.9  christos 	{ STRe(phase1, phase1) },
   2578  1.9  christos 	{ STRe(phase2, phase2) },
   2579  1.9  christos 	{ STRe(machine_phase2, machine_phase2) },
   2580  1.9  christos 	{ STRe(pcsc, pcsc) },
   2581  1.9  christos 	{ STR_KEYe(pin, cert.pin) },
   2582  1.9  christos 	{ STRe(engine_id, cert.engine_id) },
   2583  1.9  christos 	{ STRe(key_id, cert.key_id) },
   2584  1.9  christos 	{ STRe(cert_id, cert.cert_id) },
   2585  1.9  christos 	{ STRe(ca_cert_id, cert.ca_cert_id) },
   2586  1.9  christos 	{ STR_KEYe(pin2, phase2_cert.pin) },
   2587  1.9  christos 	{ STRe(engine_id2, phase2_cert.engine_id) },
   2588  1.9  christos 	{ STRe(key_id2, phase2_cert.key_id) },
   2589  1.9  christos 	{ STRe(cert_id2, phase2_cert.cert_id) },
   2590  1.9  christos 	{ STRe(ca_cert_id2, phase2_cert.ca_cert_id) },
   2591  1.9  christos 	{ INTe(engine, cert.engine) },
   2592  1.9  christos 	{ INTe(engine2, phase2_cert.engine) },
   2593  1.9  christos 	{ STRe(machine_ca_cert, machine_cert.ca_cert) },
   2594  1.9  christos 	{ STRe(machine_ca_path, machine_cert.ca_path) },
   2595  1.9  christos 	{ STRe(machine_client_cert, machine_cert.client_cert) },
   2596  1.9  christos 	{ STRe(machine_private_key, machine_cert.private_key) },
   2597  1.9  christos 	{ STR_KEYe(machine_private_key_passwd,
   2598  1.9  christos 		   machine_cert.private_key_passwd) },
   2599  1.9  christos 	{ STRe(machine_subject_match, machine_cert.subject_match) },
   2600  1.9  christos 	{ STRe(machine_check_cert_subject, machine_cert.check_cert_subject) },
   2601  1.9  christos 	{ STRe(machine_altsubject_match, machine_cert.altsubject_match) },
   2602  1.9  christos 	{ STRe(machine_domain_suffix_match,
   2603  1.9  christos 	       machine_cert.domain_suffix_match) },
   2604  1.9  christos 	{ STRe(machine_domain_match, machine_cert.domain_match) },
   2605  1.9  christos 	{ STR_KEYe(machine_pin, machine_cert.pin) },
   2606  1.9  christos 	{ STRe(machine_engine_id, machine_cert.engine_id) },
   2607  1.9  christos 	{ STRe(machine_key_id, machine_cert.key_id) },
   2608  1.9  christos 	{ STRe(machine_cert_id, machine_cert.cert_id) },
   2609  1.9  christos 	{ STRe(machine_ca_cert_id, machine_cert.ca_cert_id) },
   2610  1.9  christos 	{ INTe(machine_engine, machine_cert.engine) },
   2611  1.9  christos 	{ INTe(machine_ocsp, machine_cert.ocsp) },
   2612  1.1  christos 	{ INT(eapol_flags) },
   2613  1.9  christos 	{ INTe(sim_num, sim_num) },
   2614  1.9  christos 	{ STRe(imsi_privacy_cert, imsi_privacy_cert) },
   2615  1.9  christos 	{ STRe(imsi_privacy_attr, imsi_privacy_attr) },
   2616  1.9  christos 	{ STRe(openssl_ciphers, openssl_ciphers) },
   2617  1.9  christos 	{ INTe(erp, erp) },
   2618  1.1  christos #endif /* IEEE8021X_EAPOL */
   2619  1.9  christos #ifdef CONFIG_WEP
   2620  1.1  christos 	{ FUNC_KEY(wep_key0) },
   2621  1.1  christos 	{ FUNC_KEY(wep_key1) },
   2622  1.1  christos 	{ FUNC_KEY(wep_key2) },
   2623  1.1  christos 	{ FUNC_KEY(wep_key3) },
   2624  1.1  christos 	{ INT(wep_tx_keyidx) },
   2625  1.9  christos #endif /* CONFIG_WEP */
   2626  1.1  christos 	{ INT(priority) },
   2627  1.1  christos #ifdef IEEE8021X_EAPOL
   2628  1.1  christos 	{ INT(eap_workaround) },
   2629  1.9  christos 	{ STRe(pac_file, pac_file) },
   2630  1.9  christos 	{ INTe(fragment_size, fragment_size) },
   2631  1.9  christos 	{ INTe(ocsp, cert.ocsp) },
   2632  1.9  christos 	{ INTe(ocsp2, phase2_cert.ocsp) },
   2633  1.1  christos #endif /* IEEE8021X_EAPOL */
   2634  1.2  christos #ifdef CONFIG_MESH
   2635  1.2  christos 	{ INT_RANGE(mode, 0, 5) },
   2636  1.2  christos 	{ INT_RANGE(no_auto_peer, 0, 1) },
   2637  1.9  christos 	{ INT_RANGE(mesh_fwding, 0, 1) },
   2638  1.7  christos 	{ INT_RANGE(mesh_rssi_threshold, -255, 1) },
   2639  1.2  christos #else /* CONFIG_MESH */
   2640  1.2  christos 	{ INT_RANGE(mode, 0, 4) },
   2641  1.2  christos #endif /* CONFIG_MESH */
   2642  1.1  christos 	{ INT_RANGE(proactive_key_caching, 0, 1) },
   2643  1.2  christos 	{ INT_RANGE(disabled, 0, 2) },
   2644  1.1  christos 	{ STR(id_str) },
   2645  1.1  christos 	{ INT_RANGE(ieee80211w, 0, 2) },
   2646  1.8  christos #ifdef CONFIG_OCV
   2647  1.8  christos 	{ FUNC(ocv) },
   2648  1.8  christos #endif /* CONFIG_OCV */
   2649  1.7  christos 	{ FUNC(peerkey) /* obsolete - removed */ },
   2650  1.1  christos 	{ INT_RANGE(mixed_cell, 0, 1) },
   2651  1.9  christos 	{ INT_RANGE(frequency, 0, 70200) },
   2652  1.2  christos 	{ INT_RANGE(fixed_freq, 0, 1) },
   2653  1.9  christos 	{ INT_RANGE(enable_edmg, 0, 1) },
   2654  1.9  christos 	{ INT_RANGE(edmg_channel, 9, 13) },
   2655  1.6  christos #ifdef CONFIG_ACS
   2656  1.6  christos 	{ INT_RANGE(acs, 0, 1) },
   2657  1.6  christos #endif /* CONFIG_ACS */
   2658  1.2  christos #ifdef CONFIG_MESH
   2659  1.2  christos 	{ FUNC(mesh_basic_rates) },
   2660  1.2  christos 	{ INT(dot11MeshMaxRetries) },
   2661  1.2  christos 	{ INT(dot11MeshRetryTimeout) },
   2662  1.2  christos 	{ INT(dot11MeshConfirmTimeout) },
   2663  1.2  christos 	{ INT(dot11MeshHoldingTimeout) },
   2664  1.2  christos #endif /* CONFIG_MESH */
   2665  1.1  christos 	{ INT(wpa_ptk_rekey) },
   2666  1.9  christos 	{ INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) },
   2667  1.6  christos 	{ INT(group_rekey) },
   2668  1.1  christos 	{ STR(bgscan) },
   2669  1.2  christos 	{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
   2670  1.2  christos #ifdef CONFIG_P2P
   2671  1.2  christos 	{ FUNC(go_p2p_dev_addr) },
   2672  1.2  christos 	{ FUNC(p2p_client_list) },
   2673  1.2  christos 	{ FUNC(psk_list) },
   2674  1.2  christos #endif /* CONFIG_P2P */
   2675  1.2  christos #ifdef CONFIG_HT_OVERRIDES
   2676  1.2  christos 	{ INT_RANGE(disable_ht, 0, 1) },
   2677  1.9  christos 	{ INT_RANGE(disable_ht40, 0, 1) },
   2678  1.2  christos 	{ INT_RANGE(disable_sgi, 0, 1) },
   2679  1.2  christos 	{ INT_RANGE(disable_ldpc, 0, 1) },
   2680  1.2  christos 	{ INT_RANGE(ht40_intolerant, 0, 1) },
   2681  1.8  christos 	{ INT_RANGE(tx_stbc, -1, 1) },
   2682  1.8  christos 	{ INT_RANGE(rx_stbc, -1, 3) },
   2683  1.2  christos 	{ INT_RANGE(disable_max_amsdu, -1, 1) },
   2684  1.2  christos 	{ INT_RANGE(ampdu_factor, -1, 3) },
   2685  1.2  christos 	{ INT_RANGE(ampdu_density, -1, 7) },
   2686  1.2  christos 	{ STR(ht_mcs) },
   2687  1.2  christos #endif /* CONFIG_HT_OVERRIDES */
   2688  1.2  christos #ifdef CONFIG_VHT_OVERRIDES
   2689  1.2  christos 	{ INT_RANGE(disable_vht, 0, 1) },
   2690  1.2  christos 	{ INT(vht_capa) },
   2691  1.2  christos 	{ INT(vht_capa_mask) },
   2692  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_1, -1, 3) },
   2693  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_2, -1, 3) },
   2694  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_3, -1, 3) },
   2695  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_4, -1, 3) },
   2696  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_5, -1, 3) },
   2697  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_6, -1, 3) },
   2698  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_7, -1, 3) },
   2699  1.2  christos 	{ INT_RANGE(vht_rx_mcs_nss_8, -1, 3) },
   2700  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_1, -1, 3) },
   2701  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_2, -1, 3) },
   2702  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_3, -1, 3) },
   2703  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_4, -1, 3) },
   2704  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_5, -1, 3) },
   2705  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_6, -1, 3) },
   2706  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_7, -1, 3) },
   2707  1.2  christos 	{ INT_RANGE(vht_tx_mcs_nss_8, -1, 3) },
   2708  1.2  christos #endif /* CONFIG_VHT_OVERRIDES */
   2709  1.9  christos #ifdef CONFIG_HE_OVERRIDES
   2710  1.9  christos 	{ INT_RANGE(disable_he, 0, 1)},
   2711  1.9  christos #endif /* CONFIG_HE_OVERRIDES */
   2712  1.2  christos 	{ INT(ap_max_inactivity) },
   2713  1.2  christos 	{ INT(dtim_period) },
   2714  1.2  christos 	{ INT(beacon_int) },
   2715  1.2  christos #ifdef CONFIG_MACSEC
   2716  1.2  christos 	{ INT_RANGE(macsec_policy, 0, 1) },
   2717  1.7  christos 	{ INT_RANGE(macsec_integ_only, 0, 1) },
   2718  1.8  christos 	{ INT_RANGE(macsec_replay_protect, 0, 1) },
   2719  1.8  christos 	{ INT(macsec_replay_window) },
   2720  1.9  christos 	{ INT_RANGE(macsec_offload, 0, 2) },
   2721  1.7  christos 	{ INT_RANGE(macsec_port, 1, 65534) },
   2722  1.7  christos 	{ INT_RANGE(mka_priority, 0, 255) },
   2723  1.9  christos 	{ INT_RANGE(macsec_csindex, 0, 1) },
   2724  1.7  christos 	{ FUNC_KEY(mka_cak) },
   2725  1.7  christos 	{ FUNC_KEY(mka_ckn) },
   2726  1.2  christos #endif /* CONFIG_MACSEC */
   2727  1.2  christos #ifdef CONFIG_HS20
   2728  1.2  christos 	{ INT(update_identifier) },
   2729  1.7  christos 	{ STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) },
   2730  1.2  christos #endif /* CONFIG_HS20 */
   2731  1.9  christos 	{ INT_RANGE(mac_addr, 0, 3) },
   2732  1.9  christos 	{ FUNC_KEY(mac_value) },
   2733  1.6  christos 	{ INT_RANGE(pbss, 0, 2) },
   2734  1.6  christos 	{ INT_RANGE(wps_disabled, 0, 1) },
   2735  1.7  christos 	{ INT_RANGE(fils_dh_group, 0, 65535) },
   2736  1.7  christos #ifdef CONFIG_DPP
   2737  1.7  christos 	{ STR(dpp_connector) },
   2738  1.7  christos 	{ STR_LEN(dpp_netaccesskey) },
   2739  1.7  christos 	{ INT(dpp_netaccesskey_expiry) },
   2740  1.7  christos 	{ STR_LEN(dpp_csign) },
   2741  1.9  christos 	{ STR_LEN(dpp_pp_key) },
   2742  1.9  christos 	{ INT_RANGE(dpp_pfs, 0, 2) },
   2743  1.9  christos 	{ INT_RANGE(dpp_connector_privacy, 0, 1) },
   2744  1.7  christos #endif /* CONFIG_DPP */
   2745  1.7  christos 	{ INT_RANGE(owe_group, 0, 65535) },
   2746  1.7  christos 	{ INT_RANGE(owe_only, 0, 1) },
   2747  1.9  christos 	{ INT_RANGE(owe_ptk_workaround, 0, 1) },
   2748  1.8  christos 	{ INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
   2749  1.8  christos 	{ INT_RANGE(ft_eap_pmksa_caching, 0, 1) },
   2750  1.9  christos 	{ INT_RANGE(multi_ap_profile, MULTI_AP_PROFILE_1,
   2751  1.9  christos 		    MULTI_AP_PROFILE_MAX) },
   2752  1.9  christos 	{ INT_RANGE(beacon_prot, 0, 1) },
   2753  1.9  christos 	{ INT_RANGE(transition_disable, 0, 255) },
   2754  1.9  christos 	{ INT_RANGE(sae_pk, 0, 2) },
   2755  1.9  christos 	{ INT_RANGE(disable_eht, 0, 1)},
   2756  1.9  christos 	{ INT_RANGE(enable_4addr_mode, 0, 1)},
   2757  1.9  christos 	{ INT_RANGE(max_idle, 0, 65535)},
   2758  1.9  christos 	{ INT_RANGE(ssid_protection, 0, 1)},
   2759  1.1  christos };
   2760  1.1  christos 
   2761  1.1  christos #undef OFFSET
   2762  1.1  christos #undef _STR
   2763  1.1  christos #undef STR
   2764  1.1  christos #undef STR_KEY
   2765  1.1  christos #undef _STR_LEN
   2766  1.1  christos #undef STR_LEN
   2767  1.1  christos #undef STR_LEN_KEY
   2768  1.1  christos #undef _STR_RANGE
   2769  1.1  christos #undef STR_RANGE
   2770  1.1  christos #undef STR_RANGE_KEY
   2771  1.1  christos #undef _INT
   2772  1.1  christos #undef INT
   2773  1.1  christos #undef INT_RANGE
   2774  1.1  christos #undef _FUNC
   2775  1.1  christos #undef FUNC
   2776  1.1  christos #undef FUNC_KEY
   2777  1.2  christos #define NUM_SSID_FIELDS ARRAY_SIZE(ssid_fields)
   2778  1.1  christos 
   2779  1.1  christos 
   2780  1.1  christos /**
   2781  1.1  christos  * wpa_config_add_prio_network - Add a network to priority lists
   2782  1.1  christos  * @config: Configuration data from wpa_config_read()
   2783  1.1  christos  * @ssid: Pointer to the network configuration to be added to the list
   2784  1.1  christos  * Returns: 0 on success, -1 on failure
   2785  1.1  christos  *
   2786  1.1  christos  * This function is used to add a network block to the priority list of
   2787  1.1  christos  * networks. This must be called for each network when reading in the full
   2788  1.1  christos  * configuration. In addition, this can be used indirectly when updating
   2789  1.1  christos  * priorities by calling wpa_config_update_prio_list().
   2790  1.1  christos  */
   2791  1.1  christos int wpa_config_add_prio_network(struct wpa_config *config,
   2792  1.1  christos 				struct wpa_ssid *ssid)
   2793  1.1  christos {
   2794  1.9  christos 	size_t prio;
   2795  1.1  christos 	struct wpa_ssid *prev, **nlist;
   2796  1.1  christos 
   2797  1.1  christos 	/*
   2798  1.1  christos 	 * Add to an existing priority list if one is available for the
   2799  1.1  christos 	 * configured priority level for this network.
   2800  1.1  christos 	 */
   2801  1.1  christos 	for (prio = 0; prio < config->num_prio; prio++) {
   2802  1.1  christos 		prev = config->pssid[prio];
   2803  1.1  christos 		if (prev->priority == ssid->priority) {
   2804  1.1  christos 			while (prev->pnext)
   2805  1.1  christos 				prev = prev->pnext;
   2806  1.1  christos 			prev->pnext = ssid;
   2807  1.1  christos 			return 0;
   2808  1.1  christos 		}
   2809  1.1  christos 	}
   2810  1.1  christos 
   2811  1.1  christos 	/* First network for this priority - add a new priority list */
   2812  1.2  christos 	nlist = os_realloc_array(config->pssid, config->num_prio + 1,
   2813  1.2  christos 				 sizeof(struct wpa_ssid *));
   2814  1.1  christos 	if (nlist == NULL)
   2815  1.1  christos 		return -1;
   2816  1.1  christos 
   2817  1.1  christos 	for (prio = 0; prio < config->num_prio; prio++) {
   2818  1.2  christos 		if (nlist[prio]->priority < ssid->priority) {
   2819  1.2  christos 			os_memmove(&nlist[prio + 1], &nlist[prio],
   2820  1.2  christos 				   (config->num_prio - prio) *
   2821  1.2  christos 				   sizeof(struct wpa_ssid *));
   2822  1.1  christos 			break;
   2823  1.2  christos 		}
   2824  1.1  christos 	}
   2825  1.1  christos 
   2826  1.1  christos 	nlist[prio] = ssid;
   2827  1.1  christos 	config->num_prio++;
   2828  1.1  christos 	config->pssid = nlist;
   2829  1.1  christos 
   2830  1.1  christos 	return 0;
   2831  1.1  christos }
   2832  1.1  christos 
   2833  1.1  christos 
   2834  1.1  christos /**
   2835  1.1  christos  * wpa_config_update_prio_list - Update network priority list
   2836  1.1  christos  * @config: Configuration data from wpa_config_read()
   2837  1.1  christos  * Returns: 0 on success, -1 on failure
   2838  1.1  christos  *
   2839  1.1  christos  * This function is called to update the priority list of networks in the
   2840  1.1  christos  * configuration when a network is being added or removed. This is also called
   2841  1.1  christos  * if a priority for a network is changed.
   2842  1.1  christos  */
   2843  1.1  christos int wpa_config_update_prio_list(struct wpa_config *config)
   2844  1.1  christos {
   2845  1.1  christos 	struct wpa_ssid *ssid;
   2846  1.1  christos 	int ret = 0;
   2847  1.1  christos 
   2848  1.1  christos 	os_free(config->pssid);
   2849  1.1  christos 	config->pssid = NULL;
   2850  1.1  christos 	config->num_prio = 0;
   2851  1.1  christos 
   2852  1.1  christos 	ssid = config->ssid;
   2853  1.1  christos 	while (ssid) {
   2854  1.1  christos 		ssid->pnext = NULL;
   2855  1.1  christos 		if (wpa_config_add_prio_network(config, ssid) < 0)
   2856  1.1  christos 			ret = -1;
   2857  1.1  christos 		ssid = ssid->next;
   2858  1.1  christos 	}
   2859  1.1  christos 
   2860  1.1  christos 	return ret;
   2861  1.1  christos }
   2862  1.1  christos 
   2863  1.1  christos 
   2864  1.1  christos #ifdef IEEE8021X_EAPOL
   2865  1.9  christos 
   2866  1.9  christos static void eap_peer_config_free_cert(struct eap_peer_cert_config *cert)
   2867  1.9  christos {
   2868  1.9  christos 	os_free(cert->ca_cert);
   2869  1.9  christos 	os_free(cert->ca_path);
   2870  1.9  christos 	os_free(cert->client_cert);
   2871  1.9  christos 	os_free(cert->private_key);
   2872  1.9  christos 	str_clear_free(cert->private_key_passwd);
   2873  1.9  christos 	os_free(cert->subject_match);
   2874  1.9  christos 	os_free(cert->check_cert_subject);
   2875  1.9  christos 	os_free(cert->altsubject_match);
   2876  1.9  christos 	os_free(cert->domain_suffix_match);
   2877  1.9  christos 	os_free(cert->domain_match);
   2878  1.9  christos 	str_clear_free(cert->pin);
   2879  1.9  christos 	os_free(cert->engine_id);
   2880  1.9  christos 	os_free(cert->key_id);
   2881  1.9  christos 	os_free(cert->cert_id);
   2882  1.9  christos 	os_free(cert->ca_cert_id);
   2883  1.9  christos }
   2884  1.9  christos 
   2885  1.9  christos 
   2886  1.1  christos static void eap_peer_config_free(struct eap_peer_config *eap)
   2887  1.1  christos {
   2888  1.1  christos 	os_free(eap->eap_methods);
   2889  1.2  christos 	bin_clear_free(eap->identity, eap->identity_len);
   2890  1.1  christos 	os_free(eap->anonymous_identity);
   2891  1.7  christos 	os_free(eap->imsi_identity);
   2892  1.9  christos 	os_free(eap->imsi_privacy_cert);
   2893  1.9  christos 	os_free(eap->imsi_privacy_attr);
   2894  1.9  christos 	os_free(eap->machine_identity);
   2895  1.2  christos 	bin_clear_free(eap->password, eap->password_len);
   2896  1.9  christos 	bin_clear_free(eap->machine_password, eap->machine_password_len);
   2897  1.9  christos 	eap_peer_config_free_cert(&eap->cert);
   2898  1.9  christos 	eap_peer_config_free_cert(&eap->phase2_cert);
   2899  1.9  christos 	eap_peer_config_free_cert(&eap->machine_cert);
   2900  1.1  christos 	os_free(eap->phase1);
   2901  1.1  christos 	os_free(eap->phase2);
   2902  1.9  christos 	os_free(eap->machine_phase2);
   2903  1.1  christos 	os_free(eap->pcsc);
   2904  1.1  christos 	os_free(eap->otp);
   2905  1.1  christos 	os_free(eap->pending_req_otp);
   2906  1.1  christos 	os_free(eap->pac_file);
   2907  1.2  christos 	bin_clear_free(eap->new_password, eap->new_password_len);
   2908  1.2  christos 	str_clear_free(eap->external_sim_resp);
   2909  1.2  christos 	os_free(eap->openssl_ciphers);
   2910  1.1  christos }
   2911  1.9  christos 
   2912  1.1  christos #endif /* IEEE8021X_EAPOL */
   2913  1.1  christos 
   2914  1.1  christos 
   2915  1.1  christos /**
   2916  1.1  christos  * wpa_config_free_ssid - Free network/ssid configuration data
   2917  1.1  christos  * @ssid: Configuration data for the network
   2918  1.1  christos  *
   2919  1.1  christos  * This function frees all resources allocated for the network configuration
   2920  1.1  christos  * data.
   2921  1.1  christos  */
   2922  1.1  christos void wpa_config_free_ssid(struct wpa_ssid *ssid)
   2923  1.1  christos {
   2924  1.2  christos 	struct psk_list_entry *psk;
   2925  1.2  christos 
   2926  1.1  christos 	os_free(ssid->ssid);
   2927  1.2  christos 	str_clear_free(ssid->passphrase);
   2928  1.2  christos 	os_free(ssid->ext_psk);
   2929  1.7  christos 	str_clear_free(ssid->sae_password);
   2930  1.7  christos 	os_free(ssid->sae_password_id);
   2931  1.1  christos #ifdef IEEE8021X_EAPOL
   2932  1.1  christos 	eap_peer_config_free(&ssid->eap);
   2933  1.1  christos #endif /* IEEE8021X_EAPOL */
   2934  1.1  christos 	os_free(ssid->id_str);
   2935  1.1  christos 	os_free(ssid->scan_freq);
   2936  1.1  christos 	os_free(ssid->freq_list);
   2937  1.1  christos 	os_free(ssid->bgscan);
   2938  1.2  christos 	os_free(ssid->p2p_client_list);
   2939  1.9  christos 	os_free(ssid->bssid_ignore);
   2940  1.9  christos 	os_free(ssid->bssid_accept);
   2941  1.2  christos #ifdef CONFIG_HT_OVERRIDES
   2942  1.2  christos 	os_free(ssid->ht_mcs);
   2943  1.2  christos #endif /* CONFIG_HT_OVERRIDES */
   2944  1.2  christos #ifdef CONFIG_MESH
   2945  1.2  christos 	os_free(ssid->mesh_basic_rates);
   2946  1.2  christos #endif /* CONFIG_MESH */
   2947  1.7  christos #ifdef CONFIG_HS20
   2948  1.7  christos 	os_free(ssid->roaming_consortium_selection);
   2949  1.7  christos #endif /* CONFIG_HS20 */
   2950  1.7  christos 	os_free(ssid->dpp_connector);
   2951  1.7  christos 	bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len);
   2952  1.7  christos 	os_free(ssid->dpp_csign);
   2953  1.9  christos 	os_free(ssid->dpp_pp_key);
   2954  1.2  christos 	while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
   2955  1.2  christos 				    list))) {
   2956  1.2  christos 		dl_list_del(&psk->list);
   2957  1.2  christos 		bin_clear_free(psk, sizeof(*psk));
   2958  1.2  christos 	}
   2959  1.9  christos #ifdef CONFIG_SAE
   2960  1.9  christos 	sae_deinit_pt(ssid->pt);
   2961  1.9  christos #endif /* CONFIG_SAE */
   2962  1.2  christos 	bin_clear_free(ssid, sizeof(*ssid));
   2963  1.2  christos }
   2964  1.2  christos 
   2965  1.2  christos 
   2966  1.2  christos void wpa_config_free_cred(struct wpa_cred *cred)
   2967  1.2  christos {
   2968  1.2  christos 	size_t i;
   2969  1.2  christos 
   2970  1.2  christos 	os_free(cred->realm);
   2971  1.2  christos 	str_clear_free(cred->username);
   2972  1.2  christos 	str_clear_free(cred->password);
   2973  1.2  christos 	os_free(cred->ca_cert);
   2974  1.2  christos 	os_free(cred->client_cert);
   2975  1.2  christos 	os_free(cred->private_key);
   2976  1.2  christos 	str_clear_free(cred->private_key_passwd);
   2977  1.9  christos 	os_free(cred->engine_id);
   2978  1.9  christos 	os_free(cred->ca_cert_id);
   2979  1.9  christos 	os_free(cred->cert_id);
   2980  1.9  christos 	os_free(cred->key_id);
   2981  1.2  christos 	os_free(cred->imsi);
   2982  1.2  christos 	str_clear_free(cred->milenage);
   2983  1.2  christos 	for (i = 0; i < cred->num_domain; i++)
   2984  1.2  christos 		os_free(cred->domain[i]);
   2985  1.2  christos 	os_free(cred->domain);
   2986  1.2  christos 	os_free(cred->domain_suffix_match);
   2987  1.2  christos 	os_free(cred->eap_method);
   2988  1.2  christos 	os_free(cred->phase1);
   2989  1.2  christos 	os_free(cred->phase2);
   2990  1.2  christos 	os_free(cred->excluded_ssid);
   2991  1.2  christos 	os_free(cred->roaming_partner);
   2992  1.2  christos 	os_free(cred->provisioning_sp);
   2993  1.2  christos 	for (i = 0; i < cred->num_req_conn_capab; i++)
   2994  1.2  christos 		os_free(cred->req_conn_capab_port[i]);
   2995  1.2  christos 	os_free(cred->req_conn_capab_port);
   2996  1.2  christos 	os_free(cred->req_conn_capab_proto);
   2997  1.9  christos 	os_free(cred->imsi_privacy_cert);
   2998  1.9  christos 	os_free(cred->imsi_privacy_attr);
   2999  1.2  christos 	os_free(cred);
   3000  1.2  christos }
   3001  1.2  christos 
   3002  1.2  christos 
   3003  1.2  christos void wpa_config_flush_blobs(struct wpa_config *config)
   3004  1.2  christos {
   3005  1.2  christos #ifndef CONFIG_NO_CONFIG_BLOBS
   3006  1.2  christos 	struct wpa_config_blob *blob, *prev;
   3007  1.2  christos 
   3008  1.2  christos 	blob = config->blobs;
   3009  1.2  christos 	config->blobs = NULL;
   3010  1.2  christos 	while (blob) {
   3011  1.2  christos 		prev = blob;
   3012  1.2  christos 		blob = blob->next;
   3013  1.2  christos 		wpa_config_free_blob(prev);
   3014  1.2  christos 	}
   3015  1.2  christos #endif /* CONFIG_NO_CONFIG_BLOBS */
   3016  1.1  christos }
   3017  1.1  christos 
   3018  1.1  christos 
   3019  1.1  christos /**
   3020  1.1  christos  * wpa_config_free - Free configuration data
   3021  1.1  christos  * @config: Configuration data from wpa_config_read()
   3022  1.1  christos  *
   3023  1.1  christos  * This function frees all resources allocated for the configuration data by
   3024  1.1  christos  * wpa_config_read().
   3025  1.1  christos  */
   3026  1.1  christos void wpa_config_free(struct wpa_config *config)
   3027  1.1  christos {
   3028  1.1  christos 	struct wpa_ssid *ssid, *prev = NULL;
   3029  1.2  christos 	struct wpa_cred *cred, *cprev;
   3030  1.2  christos 	int i;
   3031  1.2  christos 
   3032  1.1  christos 	ssid = config->ssid;
   3033  1.1  christos 	while (ssid) {
   3034  1.1  christos 		prev = ssid;
   3035  1.1  christos 		ssid = ssid->next;
   3036  1.1  christos 		wpa_config_free_ssid(prev);
   3037  1.1  christos 	}
   3038  1.1  christos 
   3039  1.2  christos 	cred = config->cred;
   3040  1.2  christos 	while (cred) {
   3041  1.2  christos 		cprev = cred;
   3042  1.2  christos 		cred = cred->next;
   3043  1.2  christos 		wpa_config_free_cred(cprev);
   3044  1.1  christos 	}
   3045  1.1  christos 
   3046  1.2  christos 	wpa_config_flush_blobs(config);
   3047  1.2  christos 
   3048  1.2  christos 	wpabuf_free(config->wps_vendor_ext_m1);
   3049  1.2  christos 	for (i = 0; i < MAX_WPS_VENDOR_EXT; i++)
   3050  1.2  christos 		wpabuf_free(config->wps_vendor_ext[i]);
   3051  1.1  christos 	os_free(config->ctrl_interface);
   3052  1.1  christos 	os_free(config->ctrl_interface_group);
   3053  1.9  christos #ifndef CONFIG_OPENSC_ENGINE_PATH
   3054  1.1  christos 	os_free(config->opensc_engine_path);
   3055  1.9  christos #endif /* CONFIG_OPENSC_ENGINE_PATH */
   3056  1.9  christos #ifndef CONFIG_PKCS11_ENGINE_PATH
   3057  1.1  christos 	os_free(config->pkcs11_engine_path);
   3058  1.9  christos #endif /* CONFIG_PKCS11_ENGINE_PATH */
   3059  1.9  christos #ifndef CONFIG_PKCS11_MODULE_PATH
   3060  1.1  christos 	os_free(config->pkcs11_module_path);
   3061  1.9  christos #endif /* CONFIG_PKCS11_MODULE_PATH */
   3062  1.2  christos 	os_free(config->openssl_ciphers);
   3063  1.2  christos 	os_free(config->pcsc_reader);
   3064  1.2  christos 	str_clear_free(config->pcsc_pin);
   3065  1.1  christos 	os_free(config->driver_param);
   3066  1.1  christos 	os_free(config->device_name);
   3067  1.1  christos 	os_free(config->manufacturer);
   3068  1.1  christos 	os_free(config->model_name);
   3069  1.1  christos 	os_free(config->model_number);
   3070  1.1  christos 	os_free(config->serial_number);
   3071  1.1  christos 	os_free(config->config_methods);
   3072  1.2  christos 	os_free(config->p2p_ssid_postfix);
   3073  1.1  christos 	os_free(config->pssid);
   3074  1.2  christos 	os_free(config->p2p_pref_chan);
   3075  1.2  christos 	os_free(config->p2p_no_go_freq.range);
   3076  1.2  christos 	os_free(config->autoscan);
   3077  1.2  christos 	os_free(config->freq_list);
   3078  1.9  christos 	os_free(config->initial_freq_list);
   3079  1.2  christos 	wpabuf_free(config->wps_nfc_dh_pubkey);
   3080  1.2  christos 	wpabuf_free(config->wps_nfc_dh_privkey);
   3081  1.2  christos 	wpabuf_free(config->wps_nfc_dev_pw);
   3082  1.2  christos 	os_free(config->ext_password_backend);
   3083  1.2  christos 	os_free(config->sae_groups);
   3084  1.2  christos 	wpabuf_free(config->ap_vendor_elements);
   3085  1.9  christos 	wpabuf_free(config->ap_assocresp_elements);
   3086  1.2  christos 	os_free(config->osu_dir);
   3087  1.2  christos 	os_free(config->bgscan);
   3088  1.2  christos 	os_free(config->wowlan_triggers);
   3089  1.6  christos 	os_free(config->fst_group_id);
   3090  1.6  christos 	os_free(config->sched_scan_plans);
   3091  1.6  christos #ifdef CONFIG_MBO
   3092  1.6  christos 	os_free(config->non_pref_chan);
   3093  1.6  christos #endif /* CONFIG_MBO */
   3094  1.9  christos 	os_free(config->dpp_name);
   3095  1.9  christos 	os_free(config->dpp_mud_url);
   3096  1.9  christos 	os_free(config->dpp_extra_conf_req_name);
   3097  1.9  christos 	os_free(config->dpp_extra_conf_req_value);
   3098  1.6  christos 
   3099  1.1  christos 	os_free(config);
   3100  1.1  christos }
   3101  1.1  christos 
   3102  1.1  christos 
   3103  1.1  christos /**
   3104  1.2  christos  * wpa_config_foreach_network - Iterate over each configured network
   3105  1.2  christos  * @config: Configuration data from wpa_config_read()
   3106  1.2  christos  * @func: Callback function to process each network
   3107  1.2  christos  * @arg: Opaque argument to pass to callback function
   3108  1.2  christos  *
   3109  1.2  christos  * Iterate over the set of configured networks calling the specified
   3110  1.2  christos  * function for each item. We guard against callbacks removing the
   3111  1.2  christos  * supplied network.
   3112  1.2  christos  */
   3113  1.2  christos void wpa_config_foreach_network(struct wpa_config *config,
   3114  1.2  christos 				void (*func)(void *, struct wpa_ssid *),
   3115  1.2  christos 				void *arg)
   3116  1.2  christos {
   3117  1.2  christos 	struct wpa_ssid *ssid, *next;
   3118  1.2  christos 
   3119  1.2  christos 	ssid = config->ssid;
   3120  1.2  christos 	while (ssid) {
   3121  1.2  christos 		next = ssid->next;
   3122  1.2  christos 		func(arg, ssid);
   3123  1.2  christos 		ssid = next;
   3124  1.2  christos 	}
   3125  1.2  christos }
   3126  1.2  christos 
   3127  1.2  christos 
   3128  1.2  christos /**
   3129  1.1  christos  * wpa_config_get_network - Get configured network based on id
   3130  1.1  christos  * @config: Configuration data from wpa_config_read()
   3131  1.1  christos  * @id: Unique network id to search for
   3132  1.1  christos  * Returns: Network configuration or %NULL if not found
   3133  1.1  christos  */
   3134  1.1  christos struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
   3135  1.1  christos {
   3136  1.1  christos 	struct wpa_ssid *ssid;
   3137  1.1  christos 
   3138  1.1  christos 	ssid = config->ssid;
   3139  1.1  christos 	while (ssid) {
   3140  1.1  christos 		if (id == ssid->id)
   3141  1.1  christos 			break;
   3142  1.1  christos 		ssid = ssid->next;
   3143  1.1  christos 	}
   3144  1.1  christos 
   3145  1.1  christos 	return ssid;
   3146  1.1  christos }
   3147  1.1  christos 
   3148  1.1  christos 
   3149  1.1  christos /**
   3150  1.1  christos  * wpa_config_add_network - Add a new network with empty configuration
   3151  1.1  christos  * @config: Configuration data from wpa_config_read()
   3152  1.1  christos  * Returns: The new network configuration or %NULL if operation failed
   3153  1.1  christos  */
   3154  1.1  christos struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
   3155  1.1  christos {
   3156  1.1  christos 	int id;
   3157  1.1  christos 	struct wpa_ssid *ssid, *last = NULL;
   3158  1.1  christos 
   3159  1.1  christos 	id = -1;
   3160  1.1  christos 	ssid = config->ssid;
   3161  1.1  christos 	while (ssid) {
   3162  1.1  christos 		if (ssid->id > id)
   3163  1.1  christos 			id = ssid->id;
   3164  1.1  christos 		last = ssid;
   3165  1.1  christos 		ssid = ssid->next;
   3166  1.1  christos 	}
   3167  1.1  christos 	id++;
   3168  1.1  christos 
   3169  1.1  christos 	ssid = os_zalloc(sizeof(*ssid));
   3170  1.1  christos 	if (ssid == NULL)
   3171  1.1  christos 		return NULL;
   3172  1.1  christos 	ssid->id = id;
   3173  1.2  christos 	dl_list_init(&ssid->psk_list);
   3174  1.1  christos 	if (last)
   3175  1.1  christos 		last->next = ssid;
   3176  1.1  christos 	else
   3177  1.1  christos 		config->ssid = ssid;
   3178  1.1  christos 
   3179  1.1  christos 	wpa_config_update_prio_list(config);
   3180  1.1  christos 
   3181  1.1  christos 	return ssid;
   3182  1.1  christos }
   3183  1.1  christos 
   3184  1.1  christos 
   3185  1.1  christos /**
   3186  1.1  christos  * wpa_config_remove_network - Remove a configured network based on id
   3187  1.1  christos  * @config: Configuration data from wpa_config_read()
   3188  1.1  christos  * @id: Unique network id to search for
   3189  1.1  christos  * Returns: 0 on success, or -1 if the network was not found
   3190  1.1  christos  */
   3191  1.1  christos int wpa_config_remove_network(struct wpa_config *config, int id)
   3192  1.1  christos {
   3193  1.1  christos 	struct wpa_ssid *ssid, *prev = NULL;
   3194  1.1  christos 
   3195  1.1  christos 	ssid = config->ssid;
   3196  1.1  christos 	while (ssid) {
   3197  1.1  christos 		if (id == ssid->id)
   3198  1.1  christos 			break;
   3199  1.1  christos 		prev = ssid;
   3200  1.1  christos 		ssid = ssid->next;
   3201  1.1  christos 	}
   3202  1.1  christos 
   3203  1.1  christos 	if (ssid == NULL)
   3204  1.1  christos 		return -1;
   3205  1.1  christos 
   3206  1.1  christos 	if (prev)
   3207  1.1  christos 		prev->next = ssid->next;
   3208  1.1  christos 	else
   3209  1.1  christos 		config->ssid = ssid->next;
   3210  1.1  christos 
   3211  1.1  christos 	wpa_config_update_prio_list(config);
   3212  1.1  christos 	wpa_config_free_ssid(ssid);
   3213  1.1  christos 	return 0;
   3214  1.1  christos }
   3215  1.1  christos 
   3216  1.1  christos 
   3217  1.1  christos /**
   3218  1.1  christos  * wpa_config_set_network_defaults - Set network default values
   3219  1.1  christos  * @ssid: Pointer to network configuration data
   3220  1.1  christos  */
   3221  1.1  christos void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
   3222  1.1  christos {
   3223  1.1  christos 	ssid->proto = DEFAULT_PROTO;
   3224  1.1  christos 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
   3225  1.1  christos 	ssid->group_cipher = DEFAULT_GROUP;
   3226  1.1  christos 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
   3227  1.9  christos 	ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
   3228  1.2  christos 	ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
   3229  1.7  christos 	ssid->ht = 1;
   3230  1.9  christos 	ssid->vht = 1;
   3231  1.9  christos 	ssid->he = 1;
   3232  1.1  christos #ifdef IEEE8021X_EAPOL
   3233  1.1  christos 	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
   3234  1.1  christos 	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
   3235  1.1  christos 	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
   3236  1.2  christos 	ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM;
   3237  1.1  christos #endif /* IEEE8021X_EAPOL */
   3238  1.2  christos #ifdef CONFIG_MESH
   3239  1.2  christos 	ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES;
   3240  1.2  christos 	ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
   3241  1.2  christos 	ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
   3242  1.2  christos 	ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
   3243  1.9  christos 	ssid->mesh_fwding = DEFAULT_MESH_FWDING;
   3244  1.7  christos 	ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
   3245  1.2  christos #endif /* CONFIG_MESH */
   3246  1.2  christos #ifdef CONFIG_HT_OVERRIDES
   3247  1.2  christos 	ssid->disable_ht = DEFAULT_DISABLE_HT;
   3248  1.2  christos 	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
   3249  1.2  christos 	ssid->disable_sgi = DEFAULT_DISABLE_SGI;
   3250  1.2  christos 	ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
   3251  1.8  christos 	ssid->tx_stbc = DEFAULT_TX_STBC;
   3252  1.8  christos 	ssid->rx_stbc = DEFAULT_RX_STBC;
   3253  1.2  christos 	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
   3254  1.2  christos 	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
   3255  1.2  christos 	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
   3256  1.2  christos #endif /* CONFIG_HT_OVERRIDES */
   3257  1.2  christos #ifdef CONFIG_VHT_OVERRIDES
   3258  1.2  christos 	ssid->vht_rx_mcs_nss_1 = -1;
   3259  1.2  christos 	ssid->vht_rx_mcs_nss_2 = -1;
   3260  1.2  christos 	ssid->vht_rx_mcs_nss_3 = -1;
   3261  1.2  christos 	ssid->vht_rx_mcs_nss_4 = -1;
   3262  1.2  christos 	ssid->vht_rx_mcs_nss_5 = -1;
   3263  1.2  christos 	ssid->vht_rx_mcs_nss_6 = -1;
   3264  1.2  christos 	ssid->vht_rx_mcs_nss_7 = -1;
   3265  1.2  christos 	ssid->vht_rx_mcs_nss_8 = -1;
   3266  1.2  christos 	ssid->vht_tx_mcs_nss_1 = -1;
   3267  1.2  christos 	ssid->vht_tx_mcs_nss_2 = -1;
   3268  1.2  christos 	ssid->vht_tx_mcs_nss_3 = -1;
   3269  1.2  christos 	ssid->vht_tx_mcs_nss_4 = -1;
   3270  1.2  christos 	ssid->vht_tx_mcs_nss_5 = -1;
   3271  1.2  christos 	ssid->vht_tx_mcs_nss_6 = -1;
   3272  1.2  christos 	ssid->vht_tx_mcs_nss_7 = -1;
   3273  1.2  christos 	ssid->vht_tx_mcs_nss_8 = -1;
   3274  1.2  christos #endif /* CONFIG_VHT_OVERRIDES */
   3275  1.2  christos 	ssid->proactive_key_caching = -1;
   3276  1.2  christos 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
   3277  1.9  christos 	ssid->sae_pwe = DEFAULT_SAE_PWE;
   3278  1.7  christos #ifdef CONFIG_MACSEC
   3279  1.7  christos 	ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
   3280  1.7  christos #endif /* CONFIG_MACSEC */
   3281  1.9  christos 	ssid->mac_addr = WPAS_MAC_ADDR_STYLE_NOT_SET;
   3282  1.8  christos 	ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH;
   3283  1.1  christos }
   3284  1.1  christos 
   3285  1.1  christos 
   3286  1.9  christos static const char *removed_fields[] = {
   3287  1.9  christos 	"dh_file",
   3288  1.9  christos 	"dh_file2",
   3289  1.9  christos 	"machine_dh_file",
   3290  1.9  christos 	NULL
   3291  1.9  christos };
   3292  1.9  christos 
   3293  1.9  christos static bool removed_field(const char *field)
   3294  1.9  christos {
   3295  1.9  christos 	int i;
   3296  1.9  christos 
   3297  1.9  christos 	for (i = 0; removed_fields[i]; i++) {
   3298  1.9  christos 		if (os_strcmp(field, removed_fields[i]) == 0)
   3299  1.9  christos 			return true;
   3300  1.9  christos 	}
   3301  1.9  christos 
   3302  1.9  christos 	return false;
   3303  1.9  christos }
   3304  1.9  christos 
   3305  1.9  christos 
   3306  1.1  christos /**
   3307  1.1  christos  * wpa_config_set - Set a variable in network configuration
   3308  1.1  christos  * @ssid: Pointer to network configuration data
   3309  1.1  christos  * @var: Variable name, e.g., "ssid"
   3310  1.1  christos  * @value: Variable value
   3311  1.1  christos  * @line: Line number in configuration file or 0 if not used
   3312  1.6  christos  * Returns: 0 on success with possible change in the value, 1 on success with
   3313  1.6  christos  * no change to previously configured value, or -1 on failure
   3314  1.1  christos  *
   3315  1.1  christos  * This function can be used to set network configuration variables based on
   3316  1.1  christos  * both the configuration file and management interface input. The value
   3317  1.1  christos  * parameter must be in the same format as the text-based configuration file is
   3318  1.1  christos  * using. For example, strings are using double quotation marks.
   3319  1.1  christos  */
   3320  1.1  christos int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
   3321  1.1  christos 		   int line)
   3322  1.1  christos {
   3323  1.1  christos 	size_t i;
   3324  1.1  christos 	int ret = 0;
   3325  1.1  christos 
   3326  1.1  christos 	if (ssid == NULL || var == NULL || value == NULL)
   3327  1.1  christos 		return -1;
   3328  1.1  christos 
   3329  1.1  christos 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   3330  1.1  christos 		const struct parse_data *field = &ssid_fields[i];
   3331  1.1  christos 		if (os_strcmp(var, field->name) != 0)
   3332  1.1  christos 			continue;
   3333  1.1  christos 
   3334  1.6  christos 		ret = field->parser(field, ssid, line, value);
   3335  1.6  christos 		if (ret < 0) {
   3336  1.1  christos 			if (line) {
   3337  1.1  christos 				wpa_printf(MSG_ERROR, "Line %d: failed to "
   3338  1.1  christos 					   "parse %s '%s'.", line, var, value);
   3339  1.1  christos 			}
   3340  1.1  christos 			ret = -1;
   3341  1.1  christos 		}
   3342  1.9  christos #ifdef CONFIG_SAE
   3343  1.9  christos 		if (os_strcmp(var, "ssid") == 0 ||
   3344  1.9  christos 		    os_strcmp(var, "psk") == 0 ||
   3345  1.9  christos 		    os_strcmp(var, "sae_password") == 0 ||
   3346  1.9  christos 		    os_strcmp(var, "sae_password_id") == 0) {
   3347  1.9  christos 			sae_deinit_pt(ssid->pt);
   3348  1.9  christos 			ssid->pt = NULL;
   3349  1.9  christos 		}
   3350  1.9  christos #endif /* CONFIG_SAE */
   3351  1.1  christos 		break;
   3352  1.1  christos 	}
   3353  1.1  christos 	if (i == NUM_SSID_FIELDS) {
   3354  1.9  christos 		if (removed_field(var)) {
   3355  1.9  christos 			wpa_printf(MSG_INFO,
   3356  1.9  christos 				   "Line %d: Ignore removed configuration field '%s'",
   3357  1.9  christos 				   line, var);
   3358  1.9  christos 			return ret;
   3359  1.9  christos 		}
   3360  1.1  christos 		if (line) {
   3361  1.1  christos 			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
   3362  1.1  christos 				   "'%s'.", line, var);
   3363  1.1  christos 		}
   3364  1.1  christos 		ret = -1;
   3365  1.1  christos 	}
   3366  1.9  christos 	ssid->was_recently_reconfigured = true;
   3367  1.1  christos 
   3368  1.1  christos 	return ret;
   3369  1.1  christos }
   3370  1.1  christos 
   3371  1.1  christos 
   3372  1.2  christos int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
   3373  1.2  christos 			  const char *value)
   3374  1.2  christos {
   3375  1.2  christos 	size_t len;
   3376  1.2  christos 	char *buf;
   3377  1.2  christos 	int ret;
   3378  1.2  christos 
   3379  1.2  christos 	len = os_strlen(value);
   3380  1.2  christos 	buf = os_malloc(len + 3);
   3381  1.2  christos 	if (buf == NULL)
   3382  1.2  christos 		return -1;
   3383  1.2  christos 	buf[0] = '"';
   3384  1.2  christos 	os_memcpy(buf + 1, value, len);
   3385  1.2  christos 	buf[len + 1] = '"';
   3386  1.2  christos 	buf[len + 2] = '\0';
   3387  1.2  christos 	ret = wpa_config_set(ssid, var, buf, 0);
   3388  1.2  christos 	os_free(buf);
   3389  1.2  christos 	return ret;
   3390  1.2  christos }
   3391  1.2  christos 
   3392  1.2  christos 
   3393  1.1  christos /**
   3394  1.1  christos  * wpa_config_get_all - Get all options from network configuration
   3395  1.1  christos  * @ssid: Pointer to network configuration data
   3396  1.1  christos  * @get_keys: Determines if keys/passwords will be included in returned list
   3397  1.2  christos  *	(if they may be exported)
   3398  1.1  christos  * Returns: %NULL terminated list of all set keys and their values in the form
   3399  1.1  christos  * of [key1, val1, key2, val2, ... , NULL]
   3400  1.1  christos  *
   3401  1.1  christos  * This function can be used to get list of all configured network properties.
   3402  1.1  christos  * The caller is responsible for freeing the returned list and all its
   3403  1.1  christos  * elements.
   3404  1.1  christos  */
   3405  1.1  christos char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
   3406  1.1  christos {
   3407  1.6  christos #ifdef NO_CONFIG_WRITE
   3408  1.6  christos 	return NULL;
   3409  1.6  christos #else /* NO_CONFIG_WRITE */
   3410  1.1  christos 	const struct parse_data *field;
   3411  1.1  christos 	char *key, *value;
   3412  1.1  christos 	size_t i;
   3413  1.1  christos 	char **props;
   3414  1.1  christos 	int fields_num;
   3415  1.1  christos 
   3416  1.2  christos 	get_keys = get_keys && ssid->export_keys;
   3417  1.2  christos 
   3418  1.2  christos 	props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *));
   3419  1.1  christos 	if (!props)
   3420  1.1  christos 		return NULL;
   3421  1.1  christos 
   3422  1.1  christos 	fields_num = 0;
   3423  1.1  christos 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   3424  1.1  christos 		field = &ssid_fields[i];
   3425  1.1  christos 		if (field->key_data && !get_keys)
   3426  1.1  christos 			continue;
   3427  1.1  christos 		value = field->writer(field, ssid);
   3428  1.1  christos 		if (value == NULL)
   3429  1.1  christos 			continue;
   3430  1.1  christos 		if (os_strlen(value) == 0) {
   3431  1.1  christos 			os_free(value);
   3432  1.1  christos 			continue;
   3433  1.1  christos 		}
   3434  1.1  christos 
   3435  1.1  christos 		key = os_strdup(field->name);
   3436  1.1  christos 		if (key == NULL) {
   3437  1.1  christos 			os_free(value);
   3438  1.1  christos 			goto err;
   3439  1.1  christos 		}
   3440  1.1  christos 
   3441  1.1  christos 		props[fields_num * 2] = key;
   3442  1.1  christos 		props[fields_num * 2 + 1] = value;
   3443  1.1  christos 
   3444  1.1  christos 		fields_num++;
   3445  1.1  christos 	}
   3446  1.1  christos 
   3447  1.1  christos 	return props;
   3448  1.1  christos 
   3449  1.1  christos err:
   3450  1.6  christos 	for (i = 0; props[i]; i++)
   3451  1.6  christos 		os_free(props[i]);
   3452  1.1  christos 	os_free(props);
   3453  1.1  christos 	return NULL;
   3454  1.6  christos #endif /* NO_CONFIG_WRITE */
   3455  1.1  christos }
   3456  1.1  christos 
   3457  1.1  christos 
   3458  1.1  christos #ifndef NO_CONFIG_WRITE
   3459  1.1  christos /**
   3460  1.1  christos  * wpa_config_get - Get a variable in network configuration
   3461  1.1  christos  * @ssid: Pointer to network configuration data
   3462  1.1  christos  * @var: Variable name, e.g., "ssid"
   3463  1.1  christos  * Returns: Value of the variable or %NULL on failure
   3464  1.1  christos  *
   3465  1.1  christos  * This function can be used to get network configuration variables. The
   3466  1.1  christos  * returned value is a copy of the configuration variable in text format, i.e,.
   3467  1.1  christos  * the same format that the text-based configuration file and wpa_config_set()
   3468  1.1  christos  * are using for the value. The caller is responsible for freeing the returned
   3469  1.1  christos  * value.
   3470  1.1  christos  */
   3471  1.1  christos char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
   3472  1.1  christos {
   3473  1.1  christos 	size_t i;
   3474  1.1  christos 
   3475  1.1  christos 	if (ssid == NULL || var == NULL)
   3476  1.1  christos 		return NULL;
   3477  1.1  christos 
   3478  1.1  christos 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   3479  1.1  christos 		const struct parse_data *field = &ssid_fields[i];
   3480  1.3  christos 		if (os_strcmp(var, field->name) == 0) {
   3481  1.3  christos 			char *ret = field->writer(field, ssid);
   3482  1.3  christos 
   3483  1.3  christos 			if (ret && has_newline(ret)) {
   3484  1.3  christos 				wpa_printf(MSG_ERROR,
   3485  1.3  christos 					   "Found newline in value for %s; not returning it",
   3486  1.3  christos 					   var);
   3487  1.3  christos 				os_free(ret);
   3488  1.3  christos 				ret = NULL;
   3489  1.3  christos 			}
   3490  1.3  christos 
   3491  1.3  christos 			return ret;
   3492  1.3  christos 		}
   3493  1.1  christos 	}
   3494  1.1  christos 
   3495  1.1  christos 	return NULL;
   3496  1.1  christos }
   3497  1.1  christos 
   3498  1.1  christos 
   3499  1.1  christos /**
   3500  1.1  christos  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
   3501  1.1  christos  * @ssid: Pointer to network configuration data
   3502  1.1  christos  * @var: Variable name, e.g., "ssid"
   3503  1.1  christos  * Returns: Value of the variable or %NULL on failure
   3504  1.1  christos  *
   3505  1.1  christos  * This function can be used to get network configuration variable like
   3506  1.1  christos  * wpa_config_get(). The only difference is that this functions does not expose
   3507  1.1  christos  * key/password material from the configuration. In case a key/password field
   3508  1.1  christos  * is requested, the returned value is an empty string or %NULL if the variable
   3509  1.1  christos  * is not set or "*" if the variable is set (regardless of its value). The
   3510  1.1  christos  * returned value is a copy of the configuration variable in text format, i.e,.
   3511  1.1  christos  * the same format that the text-based configuration file and wpa_config_set()
   3512  1.1  christos  * are using for the value. The caller is responsible for freeing the returned
   3513  1.1  christos  * value.
   3514  1.1  christos  */
   3515  1.1  christos char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
   3516  1.1  christos {
   3517  1.1  christos 	size_t i;
   3518  1.1  christos 
   3519  1.1  christos 	if (ssid == NULL || var == NULL)
   3520  1.1  christos 		return NULL;
   3521  1.1  christos 
   3522  1.1  christos 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   3523  1.1  christos 		const struct parse_data *field = &ssid_fields[i];
   3524  1.1  christos 		if (os_strcmp(var, field->name) == 0) {
   3525  1.1  christos 			char *res = field->writer(field, ssid);
   3526  1.1  christos 			if (field->key_data) {
   3527  1.1  christos 				if (res && res[0]) {
   3528  1.1  christos 					wpa_printf(MSG_DEBUG, "Do not allow "
   3529  1.1  christos 						   "key_data field to be "
   3530  1.1  christos 						   "exposed");
   3531  1.2  christos 					str_clear_free(res);
   3532  1.1  christos 					return os_strdup("*");
   3533  1.1  christos 				}
   3534  1.1  christos 
   3535  1.1  christos 				os_free(res);
   3536  1.1  christos 				return NULL;
   3537  1.1  christos 			}
   3538  1.1  christos 			return res;
   3539  1.1  christos 		}
   3540  1.1  christos 	}
   3541  1.1  christos 
   3542  1.1  christos 	return NULL;
   3543  1.1  christos }
   3544  1.1  christos #endif /* NO_CONFIG_WRITE */
   3545  1.1  christos 
   3546  1.1  christos 
   3547  1.1  christos /**
   3548  1.1  christos  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
   3549  1.1  christos  * @ssid: Pointer to network configuration data
   3550  1.1  christos  *
   3551  1.1  christos  * This function must be called to update WPA PSK when either SSID or the
   3552  1.1  christos  * passphrase has changed for the network configuration.
   3553  1.1  christos  */
   3554  1.1  christos void wpa_config_update_psk(struct wpa_ssid *ssid)
   3555  1.1  christos {
   3556  1.1  christos #ifndef CONFIG_NO_PBKDF2
   3557  1.9  christos 	if (pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096,
   3558  1.9  christos 			ssid->psk, PMK_LEN) != 0) {
   3559  1.9  christos 		wpa_printf(MSG_ERROR, "Error in pbkdf2_sha1()");
   3560  1.9  christos 		return;
   3561  1.9  christos 	}
   3562  1.1  christos 	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
   3563  1.1  christos 			ssid->psk, PMK_LEN);
   3564  1.1  christos 	ssid->psk_set = 1;
   3565  1.1  christos #endif /* CONFIG_NO_PBKDF2 */
   3566  1.1  christos }
   3567  1.1  christos 
   3568  1.1  christos 
   3569  1.2  christos static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred,
   3570  1.2  christos 					      const char *value)
   3571  1.1  christos {
   3572  1.2  christos 	u8 *proto;
   3573  1.2  christos 	int **port;
   3574  1.2  christos 	int *ports, *nports;
   3575  1.2  christos 	const char *pos;
   3576  1.2  christos 	unsigned int num_ports;
   3577  1.2  christos 
   3578  1.2  christos 	proto = os_realloc_array(cred->req_conn_capab_proto,
   3579  1.2  christos 				 cred->num_req_conn_capab + 1, sizeof(u8));
   3580  1.2  christos 	if (proto == NULL)
   3581  1.2  christos 		return -1;
   3582  1.2  christos 	cred->req_conn_capab_proto = proto;
   3583  1.2  christos 
   3584  1.2  christos 	port = os_realloc_array(cred->req_conn_capab_port,
   3585  1.2  christos 				cred->num_req_conn_capab + 1, sizeof(int *));
   3586  1.2  christos 	if (port == NULL)
   3587  1.2  christos 		return -1;
   3588  1.2  christos 	cred->req_conn_capab_port = port;
   3589  1.2  christos 
   3590  1.2  christos 	proto[cred->num_req_conn_capab] = atoi(value);
   3591  1.2  christos 
   3592  1.2  christos 	pos = os_strchr(value, ':');
   3593  1.2  christos 	if (pos == NULL) {
   3594  1.2  christos 		port[cred->num_req_conn_capab] = NULL;
   3595  1.2  christos 		cred->num_req_conn_capab++;
   3596  1.2  christos 		return 0;
   3597  1.2  christos 	}
   3598  1.2  christos 	pos++;
   3599  1.2  christos 
   3600  1.2  christos 	ports = NULL;
   3601  1.2  christos 	num_ports = 0;
   3602  1.2  christos 
   3603  1.2  christos 	while (*pos) {
   3604  1.2  christos 		nports = os_realloc_array(ports, num_ports + 1, sizeof(int));
   3605  1.2  christos 		if (nports == NULL) {
   3606  1.2  christos 			os_free(ports);
   3607  1.2  christos 			return -1;
   3608  1.2  christos 		}
   3609  1.2  christos 		ports = nports;
   3610  1.2  christos 		ports[num_ports++] = atoi(pos);
   3611  1.2  christos 
   3612  1.2  christos 		pos = os_strchr(pos, ',');
   3613  1.2  christos 		if (pos == NULL)
   3614  1.2  christos 			break;
   3615  1.2  christos 		pos++;
   3616  1.2  christos 	}
   3617  1.1  christos 
   3618  1.2  christos 	nports = os_realloc_array(ports, num_ports + 1, sizeof(int));
   3619  1.2  christos 	if (nports == NULL) {
   3620  1.2  christos 		os_free(ports);
   3621  1.2  christos 		return -1;
   3622  1.1  christos 	}
   3623  1.2  christos 	ports = nports;
   3624  1.2  christos 	ports[num_ports] = -1;
   3625  1.2  christos 
   3626  1.2  christos 	port[cred->num_req_conn_capab] = ports;
   3627  1.2  christos 	cred->num_req_conn_capab++;
   3628  1.2  christos 	return 0;
   3629  1.1  christos }
   3630  1.1  christos 
   3631  1.1  christos 
   3632  1.9  christos static int
   3633  1.9  christos wpa_config_set_cred_ois(u8 cred_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN],
   3634  1.9  christos 			size_t cred_ois_len[MAX_ROAMING_CONS],
   3635  1.9  christos 			unsigned int *cred_num_ois,
   3636  1.9  christos 			const char *value)
   3637  1.9  christos {
   3638  1.9  christos 	u8 ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
   3639  1.9  christos 	size_t ois_len[MAX_ROAMING_CONS];
   3640  1.9  christos 	unsigned int num_ois = 0;
   3641  1.7  christos 	const char *pos, *end;
   3642  1.7  christos 	size_t len;
   3643  1.7  christos 
   3644  1.9  christos 	len = os_strlen(value);
   3645  1.9  christos 	if (len / 2 < 3) {
   3646  1.9  christos 		wpa_printf(MSG_ERROR,
   3647  1.9  christos 			   "Invalid organisation identifier (OI) list: %s",
   3648  1.9  christos 			   value);
   3649  1.9  christos 		return -1;
   3650  1.9  christos 	}
   3651  1.9  christos 
   3652  1.9  christos 	os_memset(ois, 0, sizeof(ois));
   3653  1.9  christos 	os_memset(ois_len, 0, sizeof(ois_len));
   3654  1.7  christos 
   3655  1.7  christos 	for (pos = value;;) {
   3656  1.7  christos 		end = os_strchr(pos, ',');
   3657  1.7  christos 		len = end ? (size_t) (end - pos) : os_strlen(pos);
   3658  1.7  christos 		if (!end && len == 0)
   3659  1.7  christos 			break;
   3660  1.9  christos 		if (len / 2 < 3 || (len & 1) != 0 ||
   3661  1.7  christos 		    len / 2 > MAX_ROAMING_CONS_OI_LEN ||
   3662  1.7  christos 		    hexstr2bin(pos,
   3663  1.9  christos 			       ois[num_ois],
   3664  1.7  christos 			       len / 2) < 0) {
   3665  1.7  christos 			wpa_printf(MSG_INFO,
   3666  1.9  christos 				   "Invalid organisation identifier (OI) entry: %s",
   3667  1.7  christos 				   pos);
   3668  1.7  christos 			return -1;
   3669  1.7  christos 		}
   3670  1.9  christos 		ois_len[num_ois] = len / 2;
   3671  1.9  christos 		num_ois++;
   3672  1.7  christos 
   3673  1.7  christos 		if (!end)
   3674  1.7  christos 			break;
   3675  1.7  christos 
   3676  1.9  christos 		if (num_ois >= MAX_ROAMING_CONS) {
   3677  1.7  christos 			wpa_printf(MSG_INFO,
   3678  1.9  christos 				   "Too many OIs");
   3679  1.7  christos 			return -1;
   3680  1.7  christos 		}
   3681  1.7  christos 
   3682  1.7  christos 		pos = end + 1;
   3683  1.7  christos 	}
   3684  1.7  christos 
   3685  1.9  christos 	os_memcpy(cred_ois, ois, sizeof(ois));
   3686  1.9  christos 	os_memcpy(cred_ois_len, ois_len, sizeof(ois_len));
   3687  1.9  christos 	*cred_num_ois = num_ois;
   3688  1.7  christos 
   3689  1.7  christos 	return 0;
   3690  1.7  christos }
   3691  1.7  christos 
   3692  1.7  christos 
   3693  1.2  christos int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
   3694  1.2  christos 			const char *value, int line)
   3695  1.1  christos {
   3696  1.2  christos 	char *val;
   3697  1.2  christos 	size_t len;
   3698  1.7  christos 	int res;
   3699  1.1  christos 
   3700  1.2  christos 	if (os_strcmp(var, "temporary") == 0) {
   3701  1.2  christos 		cred->temporary = atoi(value);
   3702  1.2  christos 		return 0;
   3703  1.2  christos 	}
   3704  1.1  christos 
   3705  1.2  christos 	if (os_strcmp(var, "priority") == 0) {
   3706  1.2  christos 		cred->priority = atoi(value);
   3707  1.2  christos 		return 0;
   3708  1.1  christos 	}
   3709  1.1  christos 
   3710  1.2  christos 	if (os_strcmp(var, "sp_priority") == 0) {
   3711  1.2  christos 		int prio = atoi(value);
   3712  1.2  christos 		if (prio < 0 || prio > 255)
   3713  1.2  christos 			return -1;
   3714  1.2  christos 		cred->sp_priority = prio;
   3715  1.2  christos 		return 0;
   3716  1.2  christos 	}
   3717  1.1  christos 
   3718  1.2  christos 	if (os_strcmp(var, "pcsc") == 0) {
   3719  1.2  christos 		cred->pcsc = atoi(value);
   3720  1.2  christos 		return 0;
   3721  1.2  christos 	}
   3722  1.1  christos 
   3723  1.2  christos 	if (os_strcmp(var, "eap") == 0) {
   3724  1.2  christos 		struct eap_method_type method;
   3725  1.2  christos 		method.method = eap_peer_get_type(value, &method.vendor);
   3726  1.2  christos 		if (method.vendor == EAP_VENDOR_IETF &&
   3727  1.2  christos 		    method.method == EAP_TYPE_NONE) {
   3728  1.2  christos 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' "
   3729  1.2  christos 				   "for a credential", line, value);
   3730  1.2  christos 			return -1;
   3731  1.1  christos 		}
   3732  1.2  christos 		os_free(cred->eap_method);
   3733  1.2  christos 		cred->eap_method = os_malloc(sizeof(*cred->eap_method));
   3734  1.2  christos 		if (cred->eap_method == NULL)
   3735  1.2  christos 			return -1;
   3736  1.2  christos 		os_memcpy(cred->eap_method, &method, sizeof(method));
   3737  1.2  christos 		return 0;
   3738  1.2  christos 	}
   3739  1.2  christos 
   3740  1.2  christos 	if (os_strcmp(var, "password") == 0 &&
   3741  1.2  christos 	    os_strncmp(value, "ext:", 4) == 0) {
   3742  1.4  christos 		if (has_newline(value))
   3743  1.4  christos 			return -1;
   3744  1.2  christos 		str_clear_free(cred->password);
   3745  1.2  christos 		cred->password = os_strdup(value);
   3746  1.2  christos 		cred->ext_password = 1;
   3747  1.2  christos 		return 0;
   3748  1.2  christos 	}
   3749  1.2  christos 
   3750  1.2  christos 	if (os_strcmp(var, "update_identifier") == 0) {
   3751  1.2  christos 		cred->update_identifier = atoi(value);
   3752  1.2  christos 		return 0;
   3753  1.2  christos 	}
   3754  1.2  christos 
   3755  1.2  christos 	if (os_strcmp(var, "min_dl_bandwidth_home") == 0) {
   3756  1.2  christos 		cred->min_dl_bandwidth_home = atoi(value);
   3757  1.2  christos 		return 0;
   3758  1.1  christos 	}
   3759  1.1  christos 
   3760  1.2  christos 	if (os_strcmp(var, "min_ul_bandwidth_home") == 0) {
   3761  1.2  christos 		cred->min_ul_bandwidth_home = atoi(value);
   3762  1.2  christos 		return 0;
   3763  1.2  christos 	}
   3764  1.1  christos 
   3765  1.2  christos 	if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) {
   3766  1.2  christos 		cred->min_dl_bandwidth_roaming = atoi(value);
   3767  1.2  christos 		return 0;
   3768  1.2  christos 	}
   3769  1.1  christos 
   3770  1.2  christos 	if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) {
   3771  1.2  christos 		cred->min_ul_bandwidth_roaming = atoi(value);
   3772  1.2  christos 		return 0;
   3773  1.2  christos 	}
   3774  1.2  christos 
   3775  1.2  christos 	if (os_strcmp(var, "max_bss_load") == 0) {
   3776  1.2  christos 		cred->max_bss_load = atoi(value);
   3777  1.2  christos 		return 0;
   3778  1.2  christos 	}
   3779  1.2  christos 
   3780  1.2  christos 	if (os_strcmp(var, "req_conn_capab") == 0)
   3781  1.2  christos 		return wpa_config_set_cred_req_conn_capab(cred, value);
   3782  1.2  christos 
   3783  1.2  christos 	if (os_strcmp(var, "ocsp") == 0) {
   3784  1.2  christos 		cred->ocsp = atoi(value);
   3785  1.2  christos 		return 0;
   3786  1.2  christos 	}
   3787  1.2  christos 
   3788  1.2  christos 	if (os_strcmp(var, "sim_num") == 0) {
   3789  1.2  christos 		cred->sim_num = atoi(value);
   3790  1.2  christos 		return 0;
   3791  1.2  christos 	}
   3792  1.2  christos 
   3793  1.9  christos 	if (os_strcmp(var, "engine") == 0) {
   3794  1.9  christos 		cred->engine = atoi(value);
   3795  1.9  christos 		return 0;
   3796  1.9  christos 	}
   3797  1.9  christos 
   3798  1.2  christos 	val = wpa_config_parse_string(value, &len);
   3799  1.4  christos 	if (val == NULL ||
   3800  1.4  christos 	    (os_strcmp(var, "excluded_ssid") != 0 &&
   3801  1.4  christos 	     os_strcmp(var, "roaming_consortium") != 0 &&
   3802  1.4  christos 	     os_strcmp(var, "required_roaming_consortium") != 0 &&
   3803  1.4  christos 	     has_newline(val))) {
   3804  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
   3805  1.2  christos 			   "value '%s'.", line, var, value);
   3806  1.4  christos 		os_free(val);
   3807  1.2  christos 		return -1;
   3808  1.2  christos 	}
   3809  1.2  christos 
   3810  1.2  christos 	if (os_strcmp(var, "realm") == 0) {
   3811  1.2  christos 		os_free(cred->realm);
   3812  1.2  christos 		cred->realm = val;
   3813  1.2  christos 		return 0;
   3814  1.2  christos 	}
   3815  1.2  christos 
   3816  1.2  christos 	if (os_strcmp(var, "username") == 0) {
   3817  1.2  christos 		str_clear_free(cred->username);
   3818  1.2  christos 		cred->username = val;
   3819  1.2  christos 		return 0;
   3820  1.2  christos 	}
   3821  1.2  christos 
   3822  1.2  christos 	if (os_strcmp(var, "password") == 0) {
   3823  1.2  christos 		str_clear_free(cred->password);
   3824  1.2  christos 		cred->password = val;
   3825  1.2  christos 		cred->ext_password = 0;
   3826  1.2  christos 		return 0;
   3827  1.2  christos 	}
   3828  1.2  christos 
   3829  1.2  christos 	if (os_strcmp(var, "ca_cert") == 0) {
   3830  1.2  christos 		os_free(cred->ca_cert);
   3831  1.2  christos 		cred->ca_cert = val;
   3832  1.2  christos 		return 0;
   3833  1.2  christos 	}
   3834  1.2  christos 
   3835  1.2  christos 	if (os_strcmp(var, "client_cert") == 0) {
   3836  1.2  christos 		os_free(cred->client_cert);
   3837  1.2  christos 		cred->client_cert = val;
   3838  1.2  christos 		return 0;
   3839  1.2  christos 	}
   3840  1.2  christos 
   3841  1.2  christos 	if (os_strcmp(var, "private_key") == 0) {
   3842  1.2  christos 		os_free(cred->private_key);
   3843  1.2  christos 		cred->private_key = val;
   3844  1.2  christos 		return 0;
   3845  1.2  christos 	}
   3846  1.2  christos 
   3847  1.2  christos 	if (os_strcmp(var, "private_key_passwd") == 0) {
   3848  1.2  christos 		str_clear_free(cred->private_key_passwd);
   3849  1.2  christos 		cred->private_key_passwd = val;
   3850  1.2  christos 		return 0;
   3851  1.2  christos 	}
   3852  1.2  christos 
   3853  1.9  christos 	if (os_strcmp(var, "engine_id") == 0) {
   3854  1.9  christos 		os_free(cred->engine_id);
   3855  1.9  christos 		cred->engine_id = val;
   3856  1.9  christos 		return 0;
   3857  1.9  christos 	}
   3858  1.9  christos 
   3859  1.9  christos 	if (os_strcmp(var, "ca_cert_id") == 0) {
   3860  1.9  christos 		os_free(cred->ca_cert_id);
   3861  1.9  christos 		cred->ca_cert_id = val;
   3862  1.9  christos 		return 0;
   3863  1.9  christos 	}
   3864  1.9  christos 
   3865  1.9  christos 	if (os_strcmp(var, "cert_id") == 0) {
   3866  1.9  christos 		os_free(cred->cert_id);
   3867  1.9  christos 		cred->cert_id = val;
   3868  1.9  christos 		return 0;
   3869  1.9  christos 	}
   3870  1.9  christos 
   3871  1.9  christos 	if (os_strcmp(var, "key_id") == 0) {
   3872  1.9  christos 		os_free(cred->key_id);
   3873  1.9  christos 		cred->key_id = val;
   3874  1.9  christos 		return 0;
   3875  1.9  christos 	}
   3876  1.9  christos 
   3877  1.2  christos 	if (os_strcmp(var, "imsi") == 0) {
   3878  1.2  christos 		os_free(cred->imsi);
   3879  1.2  christos 		cred->imsi = val;
   3880  1.2  christos 		return 0;
   3881  1.2  christos 	}
   3882  1.2  christos 
   3883  1.2  christos 	if (os_strcmp(var, "milenage") == 0) {
   3884  1.2  christos 		str_clear_free(cred->milenage);
   3885  1.2  christos 		cred->milenage = val;
   3886  1.2  christos 		return 0;
   3887  1.2  christos 	}
   3888  1.2  christos 
   3889  1.2  christos 	if (os_strcmp(var, "domain_suffix_match") == 0) {
   3890  1.2  christos 		os_free(cred->domain_suffix_match);
   3891  1.2  christos 		cred->domain_suffix_match = val;
   3892  1.2  christos 		return 0;
   3893  1.2  christos 	}
   3894  1.2  christos 
   3895  1.2  christos 	if (os_strcmp(var, "domain") == 0) {
   3896  1.2  christos 		char **new_domain;
   3897  1.2  christos 		new_domain = os_realloc_array(cred->domain,
   3898  1.2  christos 					      cred->num_domain + 1,
   3899  1.2  christos 					      sizeof(char *));
   3900  1.2  christos 		if (new_domain == NULL) {
   3901  1.2  christos 			os_free(val);
   3902  1.2  christos 			return -1;
   3903  1.2  christos 		}
   3904  1.2  christos 		new_domain[cred->num_domain++] = val;
   3905  1.2  christos 		cred->domain = new_domain;
   3906  1.2  christos 		return 0;
   3907  1.2  christos 	}
   3908  1.2  christos 
   3909  1.2  christos 	if (os_strcmp(var, "phase1") == 0) {
   3910  1.2  christos 		os_free(cred->phase1);
   3911  1.2  christos 		cred->phase1 = val;
   3912  1.2  christos 		return 0;
   3913  1.2  christos 	}
   3914  1.2  christos 
   3915  1.2  christos 	if (os_strcmp(var, "phase2") == 0) {
   3916  1.2  christos 		os_free(cred->phase2);
   3917  1.2  christos 		cred->phase2 = val;
   3918  1.2  christos 		return 0;
   3919  1.2  christos 	}
   3920  1.2  christos 
   3921  1.2  christos 	if (os_strcmp(var, "roaming_consortium") == 0) {
   3922  1.9  christos 		if (len < 3 || len > sizeof(cred->home_ois[0])) {
   3923  1.2  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   3924  1.2  christos 				   "roaming_consortium length %d (3..15 "
   3925  1.2  christos 				   "expected)", line, (int) len);
   3926  1.2  christos 			os_free(val);
   3927  1.2  christos 			return -1;
   3928  1.2  christos 		}
   3929  1.9  christos 		wpa_printf(MSG_WARNING,
   3930  1.9  christos 			   "Line %d: option roaming_consortium is deprecated and will be removed in the future",
   3931  1.9  christos 			   line);
   3932  1.9  christos 		os_memcpy(cred->home_ois[0], val, len);
   3933  1.9  christos 		cred->home_ois_len[0] = len;
   3934  1.9  christos 		cred->num_home_ois = 1;
   3935  1.2  christos 		os_free(val);
   3936  1.2  christos 		return 0;
   3937  1.2  christos 	}
   3938  1.2  christos 
   3939  1.2  christos 	if (os_strcmp(var, "required_roaming_consortium") == 0) {
   3940  1.9  christos 		if (len < 3 || len > sizeof(cred->required_home_ois[0])) {
   3941  1.2  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   3942  1.2  christos 				   "required_roaming_consortium length %d "
   3943  1.2  christos 				   "(3..15 expected)", line, (int) len);
   3944  1.2  christos 			os_free(val);
   3945  1.2  christos 			return -1;
   3946  1.2  christos 		}
   3947  1.9  christos 		wpa_printf(MSG_WARNING,
   3948  1.9  christos 			   "Line %d: option required_roaming_consortium is deprecated and will be removed in the future",
   3949  1.9  christos 			   line);
   3950  1.9  christos 		os_memcpy(cred->required_home_ois[0], val, len);
   3951  1.9  christos 		cred->required_home_ois_len[0] = len;
   3952  1.9  christos 		cred->num_required_home_ois = 1;
   3953  1.2  christos 		os_free(val);
   3954  1.2  christos 		return 0;
   3955  1.2  christos 	}
   3956  1.2  christos 
   3957  1.9  christos 	if (os_strcmp(var, "home_ois") == 0) {
   3958  1.9  christos 		res = wpa_config_set_cred_ois(cred->home_ois,
   3959  1.9  christos 					      cred->home_ois_len,
   3960  1.9  christos 					      &cred->num_home_ois,
   3961  1.9  christos 					      val);
   3962  1.9  christos 		if (res < 0)
   3963  1.9  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid home_ois",
   3964  1.9  christos 				   line);
   3965  1.9  christos 		os_free(val);
   3966  1.9  christos 		return res;
   3967  1.9  christos 	}
   3968  1.9  christos 
   3969  1.9  christos 	if (os_strcmp(var, "required_home_ois") == 0) {
   3970  1.9  christos 		res = wpa_config_set_cred_ois(cred->required_home_ois,
   3971  1.9  christos 					      cred->required_home_ois_len,
   3972  1.9  christos 					      &cred->num_required_home_ois,
   3973  1.9  christos 					      val);
   3974  1.9  christos 		if (res < 0)
   3975  1.9  christos 			wpa_printf(MSG_ERROR,
   3976  1.9  christos 				   "Line %d: invalid required_home_ois", line);
   3977  1.9  christos 		os_free(val);
   3978  1.9  christos 		return res;
   3979  1.9  christos 	}
   3980  1.9  christos 
   3981  1.7  christos 	if (os_strcmp(var, "roaming_consortiums") == 0) {
   3982  1.9  christos 		res = wpa_config_set_cred_ois(cred->roaming_consortiums,
   3983  1.9  christos 					      cred->roaming_consortiums_len,
   3984  1.9  christos 					      &cred->num_roaming_consortiums,
   3985  1.9  christos 					      val);
   3986  1.7  christos 		if (res < 0)
   3987  1.7  christos 			wpa_printf(MSG_ERROR,
   3988  1.7  christos 				   "Line %d: invalid roaming_consortiums",
   3989  1.7  christos 				   line);
   3990  1.7  christos 		os_free(val);
   3991  1.7  christos 		return res;
   3992  1.7  christos 	}
   3993  1.7  christos 
   3994  1.2  christos 	if (os_strcmp(var, "excluded_ssid") == 0) {
   3995  1.2  christos 		struct excluded_ssid *e;
   3996  1.2  christos 
   3997  1.6  christos 		if (len > SSID_MAX_LEN) {
   3998  1.2  christos 			wpa_printf(MSG_ERROR, "Line %d: invalid "
   3999  1.2  christos 				   "excluded_ssid length %d", line, (int) len);
   4000  1.2  christos 			os_free(val);
   4001  1.2  christos 			return -1;
   4002  1.2  christos 		}
   4003  1.2  christos 
   4004  1.2  christos 		e = os_realloc_array(cred->excluded_ssid,
   4005  1.2  christos 				     cred->num_excluded_ssid + 1,
   4006  1.2  christos 				     sizeof(struct excluded_ssid));
   4007  1.2  christos 		if (e == NULL) {
   4008  1.2  christos 			os_free(val);
   4009  1.2  christos 			return -1;
   4010  1.2  christos 		}
   4011  1.2  christos 		cred->excluded_ssid = e;
   4012  1.2  christos 
   4013  1.2  christos 		e = &cred->excluded_ssid[cred->num_excluded_ssid++];
   4014  1.2  christos 		os_memcpy(e->ssid, val, len);
   4015  1.2  christos 		e->ssid_len = len;
   4016  1.2  christos 
   4017  1.2  christos 		os_free(val);
   4018  1.2  christos 
   4019  1.2  christos 		return 0;
   4020  1.2  christos 	}
   4021  1.2  christos 
   4022  1.2  christos 	if (os_strcmp(var, "roaming_partner") == 0) {
   4023  1.2  christos 		struct roaming_partner *p;
   4024  1.2  christos 		char *pos;
   4025  1.2  christos 
   4026  1.2  christos 		p = os_realloc_array(cred->roaming_partner,
   4027  1.2  christos 				     cred->num_roaming_partner + 1,
   4028  1.2  christos 				     sizeof(struct roaming_partner));
   4029  1.2  christos 		if (p == NULL) {
   4030  1.2  christos 			os_free(val);
   4031  1.2  christos 			return -1;
   4032  1.2  christos 		}
   4033  1.2  christos 		cred->roaming_partner = p;
   4034  1.2  christos 
   4035  1.2  christos 		p = &cred->roaming_partner[cred->num_roaming_partner];
   4036  1.2  christos 
   4037  1.2  christos 		pos = os_strchr(val, ',');
   4038  1.2  christos 		if (pos == NULL) {
   4039  1.2  christos 			os_free(val);
   4040  1.2  christos 			return -1;
   4041  1.2  christos 		}
   4042  1.2  christos 		*pos++ = '\0';
   4043  1.2  christos 		if (pos - val - 1 >= (int) sizeof(p->fqdn)) {
   4044  1.2  christos 			os_free(val);
   4045  1.2  christos 			return -1;
   4046  1.2  christos 		}
   4047  1.2  christos 		os_memcpy(p->fqdn, val, pos - val);
   4048  1.2  christos 
   4049  1.2  christos 		p->exact_match = atoi(pos);
   4050  1.2  christos 
   4051  1.2  christos 		pos = os_strchr(pos, ',');
   4052  1.2  christos 		if (pos == NULL) {
   4053  1.2  christos 			os_free(val);
   4054  1.2  christos 			return -1;
   4055  1.2  christos 		}
   4056  1.2  christos 		*pos++ = '\0';
   4057  1.2  christos 
   4058  1.2  christos 		p->priority = atoi(pos);
   4059  1.2  christos 
   4060  1.2  christos 		pos = os_strchr(pos, ',');
   4061  1.2  christos 		if (pos == NULL) {
   4062  1.2  christos 			os_free(val);
   4063  1.2  christos 			return -1;
   4064  1.2  christos 		}
   4065  1.2  christos 		*pos++ = '\0';
   4066  1.2  christos 
   4067  1.2  christos 		if (os_strlen(pos) >= sizeof(p->country)) {
   4068  1.2  christos 			os_free(val);
   4069  1.2  christos 			return -1;
   4070  1.2  christos 		}
   4071  1.2  christos 		os_memcpy(p->country, pos, os_strlen(pos) + 1);
   4072  1.2  christos 
   4073  1.2  christos 		cred->num_roaming_partner++;
   4074  1.2  christos 		os_free(val);
   4075  1.2  christos 
   4076  1.2  christos 		return 0;
   4077  1.2  christos 	}
   4078  1.2  christos 
   4079  1.2  christos 	if (os_strcmp(var, "provisioning_sp") == 0) {
   4080  1.2  christos 		os_free(cred->provisioning_sp);
   4081  1.2  christos 		cred->provisioning_sp = val;
   4082  1.2  christos 		return 0;
   4083  1.2  christos 	}
   4084  1.2  christos 
   4085  1.9  christos 	if (os_strcmp(var, "imsi_privacy_cert") == 0) {
   4086  1.9  christos 		os_free(cred->imsi_privacy_cert);
   4087  1.9  christos 		cred->imsi_privacy_cert = val;
   4088  1.9  christos 		return 0;
   4089  1.9  christos 	}
   4090  1.9  christos 
   4091  1.9  christos 	if (os_strcmp(var, "imsi_privacy_attr") == 0) {
   4092  1.9  christos 		os_free(cred->imsi_privacy_attr);
   4093  1.9  christos 		cred->imsi_privacy_attr = val;
   4094  1.9  christos 		return 0;
   4095  1.9  christos 	}
   4096  1.9  christos 
   4097  1.2  christos 	if (line) {
   4098  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
   4099  1.2  christos 			   line, var);
   4100  1.2  christos 	}
   4101  1.2  christos 
   4102  1.2  christos 	os_free(val);
   4103  1.2  christos 
   4104  1.2  christos 	return -1;
   4105  1.2  christos }
   4106  1.2  christos 
   4107  1.2  christos 
   4108  1.2  christos static char * alloc_int_str(int val)
   4109  1.1  christos {
   4110  1.2  christos 	const unsigned int bufsize = 20;
   4111  1.2  christos 	char *buf;
   4112  1.2  christos 	int res;
   4113  1.1  christos 
   4114  1.2  christos 	buf = os_malloc(bufsize);
   4115  1.2  christos 	if (buf == NULL)
   4116  1.1  christos 		return NULL;
   4117  1.2  christos 	res = os_snprintf(buf, bufsize, "%d", val);
   4118  1.2  christos 	if (os_snprintf_error(bufsize, res)) {
   4119  1.2  christos 		os_free(buf);
   4120  1.2  christos 		buf = NULL;
   4121  1.2  christos 	}
   4122  1.2  christos 	return buf;
   4123  1.2  christos }
   4124  1.1  christos 
   4125  1.1  christos 
   4126  1.2  christos static char * alloc_strdup(const char *str)
   4127  1.2  christos {
   4128  1.2  christos 	if (str == NULL)
   4129  1.2  christos 		return NULL;
   4130  1.2  christos 	return os_strdup(str);
   4131  1.1  christos }
   4132  1.1  christos 
   4133  1.1  christos 
   4134  1.2  christos char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
   4135  1.1  christos {
   4136  1.2  christos 	if (os_strcmp(var, "temporary") == 0)
   4137  1.2  christos 		return alloc_int_str(cred->temporary);
   4138  1.2  christos 
   4139  1.2  christos 	if (os_strcmp(var, "priority") == 0)
   4140  1.2  christos 		return alloc_int_str(cred->priority);
   4141  1.2  christos 
   4142  1.2  christos 	if (os_strcmp(var, "sp_priority") == 0)
   4143  1.2  christos 		return alloc_int_str(cred->sp_priority);
   4144  1.2  christos 
   4145  1.2  christos 	if (os_strcmp(var, "pcsc") == 0)
   4146  1.2  christos 		return alloc_int_str(cred->pcsc);
   4147  1.2  christos 
   4148  1.2  christos 	if (os_strcmp(var, "eap") == 0) {
   4149  1.2  christos 		if (!cred->eap_method)
   4150  1.2  christos 			return NULL;
   4151  1.2  christos 		return alloc_strdup(eap_get_name(cred->eap_method[0].vendor,
   4152  1.2  christos 						 cred->eap_method[0].method));
   4153  1.2  christos 	}
   4154  1.2  christos 
   4155  1.2  christos 	if (os_strcmp(var, "update_identifier") == 0)
   4156  1.2  christos 		return alloc_int_str(cred->update_identifier);
   4157  1.2  christos 
   4158  1.2  christos 	if (os_strcmp(var, "min_dl_bandwidth_home") == 0)
   4159  1.2  christos 		return alloc_int_str(cred->min_dl_bandwidth_home);
   4160  1.2  christos 
   4161  1.2  christos 	if (os_strcmp(var, "min_ul_bandwidth_home") == 0)
   4162  1.2  christos 		return alloc_int_str(cred->min_ul_bandwidth_home);
   4163  1.2  christos 
   4164  1.2  christos 	if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0)
   4165  1.2  christos 		return alloc_int_str(cred->min_dl_bandwidth_roaming);
   4166  1.2  christos 
   4167  1.2  christos 	if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0)
   4168  1.2  christos 		return alloc_int_str(cred->min_ul_bandwidth_roaming);
   4169  1.2  christos 
   4170  1.2  christos 	if (os_strcmp(var, "max_bss_load") == 0)
   4171  1.2  christos 		return alloc_int_str(cred->max_bss_load);
   4172  1.2  christos 
   4173  1.2  christos 	if (os_strcmp(var, "req_conn_capab") == 0) {
   4174  1.2  christos 		unsigned int i;
   4175  1.2  christos 		char *buf, *end, *pos;
   4176  1.2  christos 		int ret;
   4177  1.2  christos 
   4178  1.2  christos 		if (!cred->num_req_conn_capab)
   4179  1.2  christos 			return NULL;
   4180  1.2  christos 
   4181  1.2  christos 		buf = os_malloc(4000);
   4182  1.2  christos 		if (buf == NULL)
   4183  1.2  christos 			return NULL;
   4184  1.2  christos 		pos = buf;
   4185  1.2  christos 		end = pos + 4000;
   4186  1.2  christos 		for (i = 0; i < cred->num_req_conn_capab; i++) {
   4187  1.2  christos 			int *ports;
   4188  1.2  christos 
   4189  1.2  christos 			ret = os_snprintf(pos, end - pos, "%s%u",
   4190  1.2  christos 					  i > 0 ? "\n" : "",
   4191  1.2  christos 					  cred->req_conn_capab_proto[i]);
   4192  1.2  christos 			if (os_snprintf_error(end - pos, ret))
   4193  1.2  christos 				return buf;
   4194  1.2  christos 			pos += ret;
   4195  1.2  christos 
   4196  1.2  christos 			ports = cred->req_conn_capab_port[i];
   4197  1.2  christos 			if (ports) {
   4198  1.2  christos 				int j;
   4199  1.2  christos 				for (j = 0; ports[j] != -1; j++) {
   4200  1.2  christos 					ret = os_snprintf(pos, end - pos,
   4201  1.2  christos 							  "%s%d",
   4202  1.2  christos 							  j > 0 ? "," : ":",
   4203  1.2  christos 							  ports[j]);
   4204  1.2  christos 					if (os_snprintf_error(end - pos, ret))
   4205  1.2  christos 						return buf;
   4206  1.2  christos 					pos += ret;
   4207  1.2  christos 				}
   4208  1.2  christos 			}
   4209  1.2  christos 		}
   4210  1.2  christos 
   4211  1.2  christos 		return buf;
   4212  1.2  christos 	}
   4213  1.2  christos 
   4214  1.2  christos 	if (os_strcmp(var, "ocsp") == 0)
   4215  1.2  christos 		return alloc_int_str(cred->ocsp);
   4216  1.2  christos 
   4217  1.2  christos 	if (os_strcmp(var, "realm") == 0)
   4218  1.2  christos 		return alloc_strdup(cred->realm);
   4219  1.2  christos 
   4220  1.2  christos 	if (os_strcmp(var, "username") == 0)
   4221  1.2  christos 		return alloc_strdup(cred->username);
   4222  1.2  christos 
   4223  1.2  christos 	if (os_strcmp(var, "password") == 0) {
   4224  1.2  christos 		if (!cred->password)
   4225  1.2  christos 			return NULL;
   4226  1.2  christos 		return alloc_strdup("*");
   4227  1.2  christos 	}
   4228  1.2  christos 
   4229  1.2  christos 	if (os_strcmp(var, "ca_cert") == 0)
   4230  1.2  christos 		return alloc_strdup(cred->ca_cert);
   4231  1.2  christos 
   4232  1.2  christos 	if (os_strcmp(var, "client_cert") == 0)
   4233  1.2  christos 		return alloc_strdup(cred->client_cert);
   4234  1.2  christos 
   4235  1.2  christos 	if (os_strcmp(var, "private_key") == 0)
   4236  1.2  christos 		return alloc_strdup(cred->private_key);
   4237  1.2  christos 
   4238  1.2  christos 	if (os_strcmp(var, "private_key_passwd") == 0) {
   4239  1.2  christos 		if (!cred->private_key_passwd)
   4240  1.2  christos 			return NULL;
   4241  1.2  christos 		return alloc_strdup("*");
   4242  1.2  christos 	}
   4243  1.2  christos 
   4244  1.2  christos 	if (os_strcmp(var, "imsi") == 0)
   4245  1.2  christos 		return alloc_strdup(cred->imsi);
   4246  1.2  christos 
   4247  1.9  christos 	if (os_strcmp(var, "imsi_privacy_cert") == 0)
   4248  1.9  christos 		return alloc_strdup(cred->imsi_privacy_cert);
   4249  1.9  christos 
   4250  1.9  christos 	if (os_strcmp(var, "imsi_privacy_attr") == 0)
   4251  1.9  christos 		return alloc_strdup(cred->imsi_privacy_attr);
   4252  1.9  christos 
   4253  1.2  christos 	if (os_strcmp(var, "milenage") == 0) {
   4254  1.2  christos 		if (!(cred->milenage))
   4255  1.2  christos 			return NULL;
   4256  1.2  christos 		return alloc_strdup("*");
   4257  1.2  christos 	}
   4258  1.2  christos 
   4259  1.2  christos 	if (os_strcmp(var, "domain_suffix_match") == 0)
   4260  1.2  christos 		return alloc_strdup(cred->domain_suffix_match);
   4261  1.2  christos 
   4262  1.2  christos 	if (os_strcmp(var, "domain") == 0) {
   4263  1.2  christos 		unsigned int i;
   4264  1.2  christos 		char *buf, *end, *pos;
   4265  1.2  christos 		int ret;
   4266  1.2  christos 
   4267  1.2  christos 		if (!cred->num_domain)
   4268  1.2  christos 			return NULL;
   4269  1.2  christos 
   4270  1.2  christos 		buf = os_malloc(4000);
   4271  1.2  christos 		if (buf == NULL)
   4272  1.2  christos 			return NULL;
   4273  1.2  christos 		pos = buf;
   4274  1.2  christos 		end = pos + 4000;
   4275  1.2  christos 
   4276  1.2  christos 		for (i = 0; i < cred->num_domain; i++) {
   4277  1.2  christos 			ret = os_snprintf(pos, end - pos, "%s%s",
   4278  1.2  christos 					  i > 0 ? "\n" : "", cred->domain[i]);
   4279  1.2  christos 			if (os_snprintf_error(end - pos, ret))
   4280  1.2  christos 				return buf;
   4281  1.2  christos 			pos += ret;
   4282  1.2  christos 		}
   4283  1.2  christos 
   4284  1.2  christos 		return buf;
   4285  1.2  christos 	}
   4286  1.2  christos 
   4287  1.2  christos 	if (os_strcmp(var, "phase1") == 0)
   4288  1.2  christos 		return alloc_strdup(cred->phase1);
   4289  1.2  christos 
   4290  1.2  christos 	if (os_strcmp(var, "phase2") == 0)
   4291  1.2  christos 		return alloc_strdup(cred->phase2);
   4292  1.2  christos 
   4293  1.2  christos 	if (os_strcmp(var, "roaming_consortium") == 0) {
   4294  1.2  christos 		size_t buflen;
   4295  1.2  christos 		char *buf;
   4296  1.2  christos 
   4297  1.9  christos 		if (!cred->num_home_ois || !cred->home_ois_len[0])
   4298  1.2  christos 			return NULL;
   4299  1.9  christos 		buflen = cred->home_ois_len[0] * 2 + 1;
   4300  1.2  christos 		buf = os_malloc(buflen);
   4301  1.2  christos 		if (buf == NULL)
   4302  1.2  christos 			return NULL;
   4303  1.9  christos 		wpa_snprintf_hex(buf, buflen, cred->home_ois[0],
   4304  1.9  christos 				 cred->home_ois_len[0]);
   4305  1.2  christos 		return buf;
   4306  1.2  christos 	}
   4307  1.2  christos 
   4308  1.2  christos 	if (os_strcmp(var, "required_roaming_consortium") == 0) {
   4309  1.2  christos 		size_t buflen;
   4310  1.2  christos 		char *buf;
   4311  1.2  christos 
   4312  1.9  christos 		if (!cred->num_required_home_ois ||
   4313  1.9  christos 		    !cred->required_home_ois_len[0])
   4314  1.2  christos 			return NULL;
   4315  1.9  christos 		buflen = cred->required_home_ois_len[0] * 2 + 1;
   4316  1.2  christos 		buf = os_malloc(buflen);
   4317  1.2  christos 		if (buf == NULL)
   4318  1.2  christos 			return NULL;
   4319  1.9  christos 		wpa_snprintf_hex(buf, buflen, cred->required_home_ois[0],
   4320  1.9  christos 				 cred->required_home_ois_len[0]);
   4321  1.9  christos 		return buf;
   4322  1.9  christos 	}
   4323  1.9  christos 
   4324  1.9  christos 	if (os_strcmp(var, "home_ois") == 0) {
   4325  1.9  christos 		size_t buflen;
   4326  1.9  christos 		char *buf, *pos;
   4327  1.9  christos 		size_t i;
   4328  1.9  christos 
   4329  1.9  christos 		if (!cred->num_home_ois)
   4330  1.9  christos 			return NULL;
   4331  1.9  christos 		buflen = cred->num_home_ois * MAX_ROAMING_CONS_OI_LEN * 2 + 1;
   4332  1.9  christos 		buf = os_malloc(buflen);
   4333  1.9  christos 		if (!buf)
   4334  1.9  christos 			return NULL;
   4335  1.9  christos 		pos = buf;
   4336  1.9  christos 		for (i = 0; i < cred->num_home_ois; i++) {
   4337  1.9  christos 			if (i > 0)
   4338  1.9  christos 				*pos++ = ',';
   4339  1.9  christos 			pos += wpa_snprintf_hex(
   4340  1.9  christos 				pos, buf + buflen - pos,
   4341  1.9  christos 				cred->home_ois[i],
   4342  1.9  christos 				cred->home_ois_len[i]);
   4343  1.9  christos 		}
   4344  1.9  christos 		*pos = '\0';
   4345  1.9  christos 		return buf;
   4346  1.9  christos 	}
   4347  1.9  christos 
   4348  1.9  christos 	if (os_strcmp(var, "required_home_ois") == 0) {
   4349  1.9  christos 		size_t buflen;
   4350  1.9  christos 		char *buf, *pos;
   4351  1.9  christos 		size_t i;
   4352  1.9  christos 
   4353  1.9  christos 		if (!cred->num_required_home_ois)
   4354  1.9  christos 			return NULL;
   4355  1.9  christos 		buflen = cred->num_required_home_ois *
   4356  1.9  christos 			MAX_ROAMING_CONS_OI_LEN * 2 + 1;
   4357  1.9  christos 		buf = os_malloc(buflen);
   4358  1.9  christos 		if (!buf)
   4359  1.9  christos 			return NULL;
   4360  1.9  christos 		pos = buf;
   4361  1.9  christos 		for (i = 0; i < cred->num_required_home_ois; i++) {
   4362  1.9  christos 			if (i > 0)
   4363  1.9  christos 				*pos++ = ',';
   4364  1.9  christos 			pos += wpa_snprintf_hex(
   4365  1.9  christos 				pos, buf + buflen - pos,
   4366  1.9  christos 				cred->required_home_ois[i],
   4367  1.9  christos 				cred->required_home_ois_len[i]);
   4368  1.9  christos 		}
   4369  1.9  christos 		*pos = '\0';
   4370  1.2  christos 		return buf;
   4371  1.2  christos 	}
   4372  1.2  christos 
   4373  1.7  christos 	if (os_strcmp(var, "roaming_consortiums") == 0) {
   4374  1.7  christos 		size_t buflen;
   4375  1.7  christos 		char *buf, *pos;
   4376  1.7  christos 		size_t i;
   4377  1.7  christos 
   4378  1.7  christos 		if (!cred->num_roaming_consortiums)
   4379  1.7  christos 			return NULL;
   4380  1.7  christos 		buflen = cred->num_roaming_consortiums *
   4381  1.7  christos 			MAX_ROAMING_CONS_OI_LEN * 2 + 1;
   4382  1.7  christos 		buf = os_malloc(buflen);
   4383  1.7  christos 		if (!buf)
   4384  1.7  christos 			return NULL;
   4385  1.7  christos 		pos = buf;
   4386  1.7  christos 		for (i = 0; i < cred->num_roaming_consortiums; i++) {
   4387  1.7  christos 			if (i > 0)
   4388  1.7  christos 				*pos++ = ',';
   4389  1.7  christos 			pos += wpa_snprintf_hex(
   4390  1.7  christos 				pos, buf + buflen - pos,
   4391  1.7  christos 				cred->roaming_consortiums[i],
   4392  1.7  christos 				cred->roaming_consortiums_len[i]);
   4393  1.7  christos 		}
   4394  1.7  christos 		*pos = '\0';
   4395  1.7  christos 		return buf;
   4396  1.7  christos 	}
   4397  1.7  christos 
   4398  1.2  christos 	if (os_strcmp(var, "excluded_ssid") == 0) {
   4399  1.2  christos 		unsigned int i;
   4400  1.2  christos 		char *buf, *end, *pos;
   4401  1.2  christos 
   4402  1.2  christos 		if (!cred->num_excluded_ssid)
   4403  1.2  christos 			return NULL;
   4404  1.2  christos 
   4405  1.2  christos 		buf = os_malloc(4000);
   4406  1.2  christos 		if (buf == NULL)
   4407  1.2  christos 			return NULL;
   4408  1.2  christos 		pos = buf;
   4409  1.2  christos 		end = pos + 4000;
   4410  1.2  christos 
   4411  1.2  christos 		for (i = 0; i < cred->num_excluded_ssid; i++) {
   4412  1.2  christos 			struct excluded_ssid *e;
   4413  1.2  christos 			int ret;
   4414  1.2  christos 
   4415  1.2  christos 			e = &cred->excluded_ssid[i];
   4416  1.2  christos 			ret = os_snprintf(pos, end - pos, "%s%s",
   4417  1.2  christos 					  i > 0 ? "\n" : "",
   4418  1.2  christos 					  wpa_ssid_txt(e->ssid, e->ssid_len));
   4419  1.2  christos 			if (os_snprintf_error(end - pos, ret))
   4420  1.2  christos 				return buf;
   4421  1.2  christos 			pos += ret;
   4422  1.2  christos 		}
   4423  1.2  christos 
   4424  1.2  christos 		return buf;
   4425  1.2  christos 	}
   4426  1.2  christos 
   4427  1.2  christos 	if (os_strcmp(var, "roaming_partner") == 0) {
   4428  1.2  christos 		unsigned int i;
   4429  1.2  christos 		char *buf, *end, *pos;
   4430  1.2  christos 
   4431  1.2  christos 		if (!cred->num_roaming_partner)
   4432  1.2  christos 			return NULL;
   4433  1.2  christos 
   4434  1.2  christos 		buf = os_malloc(4000);
   4435  1.2  christos 		if (buf == NULL)
   4436  1.2  christos 			return NULL;
   4437  1.2  christos 		pos = buf;
   4438  1.2  christos 		end = pos + 4000;
   4439  1.1  christos 
   4440  1.2  christos 		for (i = 0; i < cred->num_roaming_partner; i++) {
   4441  1.2  christos 			struct roaming_partner *p;
   4442  1.2  christos 			int ret;
   4443  1.2  christos 
   4444  1.2  christos 			p = &cred->roaming_partner[i];
   4445  1.2  christos 			ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s",
   4446  1.2  christos 					  i > 0 ? "\n" : "",
   4447  1.2  christos 					  p->fqdn, p->exact_match, p->priority,
   4448  1.2  christos 					  p->country);
   4449  1.2  christos 			if (os_snprintf_error(end - pos, ret))
   4450  1.2  christos 				return buf;
   4451  1.2  christos 			pos += ret;
   4452  1.2  christos 		}
   4453  1.2  christos 
   4454  1.2  christos 		return buf;
   4455  1.2  christos 	}
   4456  1.2  christos 
   4457  1.2  christos 	if (os_strcmp(var, "provisioning_sp") == 0)
   4458  1.2  christos 		return alloc_strdup(cred->provisioning_sp);
   4459  1.2  christos 
   4460  1.2  christos 	return NULL;
   4461  1.2  christos }
   4462  1.2  christos 
   4463  1.2  christos 
   4464  1.2  christos struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
   4465  1.2  christos {
   4466  1.2  christos 	struct wpa_cred *cred;
   4467  1.2  christos 
   4468  1.2  christos 	cred = config->cred;
   4469  1.2  christos 	while (cred) {
   4470  1.2  christos 		if (id == cred->id)
   4471  1.2  christos 			break;
   4472  1.2  christos 		cred = cred->next;
   4473  1.2  christos 	}
   4474  1.2  christos 
   4475  1.2  christos 	return cred;
   4476  1.2  christos }
   4477  1.2  christos 
   4478  1.2  christos 
   4479  1.2  christos struct wpa_cred * wpa_config_add_cred(struct wpa_config *config)
   4480  1.2  christos {
   4481  1.2  christos 	int id;
   4482  1.2  christos 	struct wpa_cred *cred, *last = NULL;
   4483  1.2  christos 
   4484  1.2  christos 	id = -1;
   4485  1.2  christos 	cred = config->cred;
   4486  1.2  christos 	while (cred) {
   4487  1.2  christos 		if (cred->id > id)
   4488  1.2  christos 			id = cred->id;
   4489  1.2  christos 		last = cred;
   4490  1.2  christos 		cred = cred->next;
   4491  1.2  christos 	}
   4492  1.2  christos 	id++;
   4493  1.2  christos 
   4494  1.2  christos 	cred = os_zalloc(sizeof(*cred));
   4495  1.2  christos 	if (cred == NULL)
   4496  1.2  christos 		return NULL;
   4497  1.2  christos 	cred->id = id;
   4498  1.2  christos 	cred->sim_num = DEFAULT_USER_SELECTED_SIM;
   4499  1.2  christos 	if (last)
   4500  1.2  christos 		last->next = cred;
   4501  1.2  christos 	else
   4502  1.2  christos 		config->cred = cred;
   4503  1.2  christos 
   4504  1.2  christos 	return cred;
   4505  1.2  christos }
   4506  1.2  christos 
   4507  1.2  christos 
   4508  1.2  christos int wpa_config_remove_cred(struct wpa_config *config, int id)
   4509  1.2  christos {
   4510  1.2  christos 	struct wpa_cred *cred, *prev = NULL;
   4511  1.2  christos 
   4512  1.2  christos 	cred = config->cred;
   4513  1.2  christos 	while (cred) {
   4514  1.2  christos 		if (id == cred->id)
   4515  1.2  christos 			break;
   4516  1.2  christos 		prev = cred;
   4517  1.2  christos 		cred = cred->next;
   4518  1.2  christos 	}
   4519  1.2  christos 
   4520  1.2  christos 	if (cred == NULL)
   4521  1.2  christos 		return -1;
   4522  1.2  christos 
   4523  1.2  christos 	if (prev)
   4524  1.2  christos 		prev->next = cred->next;
   4525  1.2  christos 	else
   4526  1.2  christos 		config->cred = cred->next;
   4527  1.2  christos 
   4528  1.2  christos 	wpa_config_free_cred(cred);
   4529  1.2  christos 	return 0;
   4530  1.2  christos }
   4531  1.2  christos 
   4532  1.2  christos 
   4533  1.2  christos #ifndef CONFIG_NO_CONFIG_BLOBS
   4534  1.2  christos /**
   4535  1.2  christos  * wpa_config_get_blob - Get a named configuration blob
   4536  1.2  christos  * @config: Configuration data from wpa_config_read()
   4537  1.2  christos  * @name: Name of the blob
   4538  1.2  christos  * Returns: Pointer to blob data or %NULL if not found
   4539  1.2  christos  */
   4540  1.2  christos const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
   4541  1.2  christos 						   const char *name)
   4542  1.2  christos {
   4543  1.2  christos 	struct wpa_config_blob *blob = config->blobs;
   4544  1.2  christos 
   4545  1.2  christos 	while (blob) {
   4546  1.2  christos 		if (os_strcmp(blob->name, name) == 0)
   4547  1.2  christos 			return blob;
   4548  1.2  christos 		blob = blob->next;
   4549  1.2  christos 	}
   4550  1.2  christos 	return NULL;
   4551  1.2  christos }
   4552  1.2  christos 
   4553  1.2  christos 
   4554  1.2  christos /**
   4555  1.2  christos  * wpa_config_set_blob - Set or add a named configuration blob
   4556  1.2  christos  * @config: Configuration data from wpa_config_read()
   4557  1.2  christos  * @blob: New value for the blob
   4558  1.2  christos  *
   4559  1.2  christos  * Adds a new configuration blob or replaces the current value of an existing
   4560  1.2  christos  * blob.
   4561  1.2  christos  */
   4562  1.2  christos void wpa_config_set_blob(struct wpa_config *config,
   4563  1.2  christos 			 struct wpa_config_blob *blob)
   4564  1.2  christos {
   4565  1.2  christos 	wpa_config_remove_blob(config, blob->name);
   4566  1.2  christos 	blob->next = config->blobs;
   4567  1.2  christos 	config->blobs = blob;
   4568  1.2  christos }
   4569  1.2  christos 
   4570  1.2  christos 
   4571  1.2  christos /**
   4572  1.2  christos  * wpa_config_free_blob - Free blob data
   4573  1.2  christos  * @blob: Pointer to blob to be freed
   4574  1.2  christos  */
   4575  1.2  christos void wpa_config_free_blob(struct wpa_config_blob *blob)
   4576  1.2  christos {
   4577  1.2  christos 	if (blob) {
   4578  1.2  christos 		os_free(blob->name);
   4579  1.2  christos 		bin_clear_free(blob->data, blob->len);
   4580  1.2  christos 		os_free(blob);
   4581  1.2  christos 	}
   4582  1.2  christos }
   4583  1.2  christos 
   4584  1.2  christos 
   4585  1.2  christos /**
   4586  1.2  christos  * wpa_config_remove_blob - Remove a named configuration blob
   4587  1.2  christos  * @config: Configuration data from wpa_config_read()
   4588  1.2  christos  * @name: Name of the blob to remove
   4589  1.2  christos  * Returns: 0 if blob was removed or -1 if blob was not found
   4590  1.2  christos  */
   4591  1.2  christos int wpa_config_remove_blob(struct wpa_config *config, const char *name)
   4592  1.2  christos {
   4593  1.2  christos 	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
   4594  1.2  christos 
   4595  1.2  christos 	while (pos) {
   4596  1.2  christos 		if (os_strcmp(pos->name, name) == 0) {
   4597  1.2  christos 			if (prev)
   4598  1.2  christos 				prev->next = pos->next;
   4599  1.2  christos 			else
   4600  1.2  christos 				config->blobs = pos->next;
   4601  1.2  christos 			wpa_config_free_blob(pos);
   4602  1.2  christos 			return 0;
   4603  1.2  christos 		}
   4604  1.2  christos 		prev = pos;
   4605  1.2  christos 		pos = pos->next;
   4606  1.2  christos 	}
   4607  1.2  christos 
   4608  1.2  christos 	return -1;
   4609  1.2  christos }
   4610  1.2  christos #endif /* CONFIG_NO_CONFIG_BLOBS */
   4611  1.2  christos 
   4612  1.2  christos 
   4613  1.2  christos /**
   4614  1.2  christos  * wpa_config_alloc_empty - Allocate an empty configuration
   4615  1.2  christos  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
   4616  1.2  christos  * socket
   4617  1.2  christos  * @driver_param: Driver parameters
   4618  1.2  christos  * Returns: Pointer to allocated configuration data or %NULL on failure
   4619  1.2  christos  */
   4620  1.2  christos struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
   4621  1.2  christos 					   const char *driver_param)
   4622  1.2  christos {
   4623  1.9  christos #define ecw2cw(ecw) ((1 << (ecw)) - 1)
   4624  1.9  christos 
   4625  1.2  christos 	struct wpa_config *config;
   4626  1.2  christos 	const int aCWmin = 4, aCWmax = 10;
   4627  1.2  christos 	const struct hostapd_wmm_ac_params ac_bk =
   4628  1.2  christos 		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
   4629  1.2  christos 	const struct hostapd_wmm_ac_params ac_be =
   4630  1.2  christos 		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
   4631  1.2  christos 	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
   4632  1.9  christos 		{ aCWmin - 1, aCWmin, 2, 3008 / 32, 0 };
   4633  1.2  christos 	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
   4634  1.9  christos 		{ aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 };
   4635  1.9  christos 	const struct hostapd_tx_queue_params txq_bk =
   4636  1.9  christos 		{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
   4637  1.9  christos 	const struct hostapd_tx_queue_params txq_be =
   4638  1.9  christos 		{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0 };
   4639  1.9  christos 	const struct hostapd_tx_queue_params txq_vi =
   4640  1.9  christos 		{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30 };
   4641  1.9  christos 	const struct hostapd_tx_queue_params txq_vo =
   4642  1.9  christos 		{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
   4643  1.9  christos 		  (ecw2cw(aCWmin) + 1) / 2 - 1, 15 };
   4644  1.9  christos 
   4645  1.9  christos #undef ecw2cw
   4646  1.2  christos 
   4647  1.2  christos 	config = os_zalloc(sizeof(*config));
   4648  1.2  christos 	if (config == NULL)
   4649  1.2  christos 		return NULL;
   4650  1.2  christos 	config->eapol_version = DEFAULT_EAPOL_VERSION;
   4651  1.2  christos 	config->ap_scan = DEFAULT_AP_SCAN;
   4652  1.2  christos 	config->user_mpm = DEFAULT_USER_MPM;
   4653  1.2  christos 	config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
   4654  1.2  christos 	config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
   4655  1.9  christos 	config->mesh_fwding = DEFAULT_MESH_FWDING;
   4656  1.6  christos 	config->dot11RSNASAERetransPeriod =
   4657  1.6  christos 		DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
   4658  1.2  christos 	config->fast_reauth = DEFAULT_FAST_REAUTH;
   4659  1.2  christos 	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
   4660  1.2  christos 	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
   4661  1.6  christos 	config->p2p_go_freq_change_policy = DEFAULT_P2P_GO_FREQ_MOVE;
   4662  1.2  christos 	config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
   4663  1.2  christos 	config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN;
   4664  1.2  christos 	config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW;
   4665  1.2  christos 	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
   4666  1.2  christos 	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
   4667  1.2  christos 	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
   4668  1.2  christos 	config->max_num_sta = DEFAULT_MAX_NUM_STA;
   4669  1.7  christos 	config->ap_isolate = DEFAULT_AP_ISOLATE;
   4670  1.2  christos 	config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
   4671  1.2  christos 	config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
   4672  1.9  christos 	config->scan_res_valid_for_connect = DEFAULT_SCAN_RES_VALID_FOR_CONNECT;
   4673  1.2  christos 	config->wmm_ac_params[0] = ac_be;
   4674  1.2  christos 	config->wmm_ac_params[1] = ac_bk;
   4675  1.2  christos 	config->wmm_ac_params[2] = ac_vi;
   4676  1.2  christos 	config->wmm_ac_params[3] = ac_vo;
   4677  1.9  christos 	config->tx_queue[0] = txq_vo;
   4678  1.9  christos 	config->tx_queue[1] = txq_vi;
   4679  1.9  christos 	config->tx_queue[2] = txq_be;
   4680  1.9  christos 	config->tx_queue[3] = txq_bk;
   4681  1.2  christos 	config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
   4682  1.2  christos 	config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
   4683  1.2  christos 	config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
   4684  1.2  christos 	config->cert_in_cb = DEFAULT_CERT_IN_CB;
   4685  1.6  christos 	config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION;
   4686  1.9  christos 	config->extended_key_id = DEFAULT_EXTENDED_KEY_ID;
   4687  1.6  christos 
   4688  1.6  christos #ifdef CONFIG_MBO
   4689  1.6  christos 	config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
   4690  1.7  christos 	config->disassoc_imminent_rssi_threshold =
   4691  1.7  christos 		DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD;
   4692  1.7  christos 	config->oce = DEFAULT_OCE_SUPPORT;
   4693  1.6  christos #endif /* CONFIG_MBO */
   4694  1.2  christos 
   4695  1.2  christos 	if (ctrl_interface)
   4696  1.2  christos 		config->ctrl_interface = os_strdup(ctrl_interface);
   4697  1.2  christos 	if (driver_param)
   4698  1.2  christos 		config->driver_param = os_strdup(driver_param);
   4699  1.7  christos 	config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
   4700  1.2  christos 
   4701  1.9  christos #ifdef CONFIG_TESTING_OPTIONS
   4702  1.9  christos 	config->mld_connect_band_pref = DEFAULT_MLD_CONNECT_BAND_PREF;
   4703  1.9  christos #endif /* CONFIG_TESTING_OPTIONS */
   4704  1.9  christos 
   4705  1.2  christos 	return config;
   4706  1.2  christos }
   4707  1.2  christos 
   4708  1.2  christos 
   4709  1.2  christos #ifndef CONFIG_NO_STDOUT_DEBUG
   4710  1.2  christos /**
   4711  1.2  christos  * wpa_config_debug_dump_networks - Debug dump of configured networks
   4712  1.2  christos  * @config: Configuration data from wpa_config_read()
   4713  1.2  christos  */
   4714  1.2  christos void wpa_config_debug_dump_networks(struct wpa_config *config)
   4715  1.2  christos {
   4716  1.9  christos 	size_t prio;
   4717  1.2  christos 	struct wpa_ssid *ssid;
   4718  1.2  christos 
   4719  1.2  christos 	for (prio = 0; prio < config->num_prio; prio++) {
   4720  1.2  christos 		ssid = config->pssid[prio];
   4721  1.2  christos 		wpa_printf(MSG_DEBUG, "Priority group %d",
   4722  1.2  christos 			   ssid->priority);
   4723  1.2  christos 		while (ssid) {
   4724  1.2  christos 			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
   4725  1.2  christos 				   ssid->id,
   4726  1.2  christos 				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
   4727  1.2  christos 			ssid = ssid->pnext;
   4728  1.1  christos 		}
   4729  1.1  christos 	}
   4730  1.1  christos }
   4731  1.1  christos #endif /* CONFIG_NO_STDOUT_DEBUG */
   4732  1.2  christos 
   4733  1.2  christos 
   4734  1.9  christos /**
   4735  1.9  christos  * Structure for global configuration parsing. This data is used to implement a
   4736  1.9  christos  * generic parser for the global interface configuration. The table of variables
   4737  1.9  christos  * is defined below in this file (global_fields[]).
   4738  1.9  christos  */
   4739  1.2  christos struct global_parse_data {
   4740  1.9  christos 	/* Configuration variable name */
   4741  1.2  christos 	char *name;
   4742  1.9  christos 
   4743  1.9  christos 	/* Parser function for this variable. The parser functions return 0 or 1
   4744  1.9  christos 	 * to indicate success. Value 0 indicates that the parameter value may
   4745  1.9  christos 	 * have changed while value 1 means that the value did not change.
   4746  1.9  christos 	 * Error cases (failure to parse the string) are indicated by returning
   4747  1.9  christos 	 * -1. */
   4748  1.2  christos 	int (*parser)(const struct global_parse_data *data,
   4749  1.2  christos 		      struct wpa_config *config, int line, const char *value);
   4750  1.9  christos 
   4751  1.9  christos 	/* Getter function to print the variable in text format to buf. */
   4752  1.2  christos 	int (*get)(const char *name, struct wpa_config *config, long offset,
   4753  1.2  christos 		   char *buf, size_t buflen, int pretty_print);
   4754  1.9  christos 
   4755  1.9  christos 	/* Variable specific parameters for the parser. */
   4756  1.2  christos 	void *param1, *param2, *param3;
   4757  1.9  christos 
   4758  1.9  christos 	/* Indicates which configuration variable has changed. */
   4759  1.2  christos 	unsigned int changed_flag;
   4760  1.2  christos };
   4761  1.2  christos 
   4762  1.2  christos 
   4763  1.9  christos static int
   4764  1.9  christos wpa_global_config_parse_int_impl(const struct global_parse_data *data,
   4765  1.9  christos 				 struct wpa_config *config, int line,
   4766  1.9  christos 				 const char *pos, bool check_range)
   4767  1.2  christos {
   4768  1.2  christos 	int val, *dst;
   4769  1.2  christos 	char *end;
   4770  1.9  christos 	bool same;
   4771  1.2  christos 
   4772  1.2  christos 	dst = (int *) (((u8 *) config) + (long) data->param1);
   4773  1.2  christos 	val = strtol(pos, &end, 0);
   4774  1.2  christos 	if (*end) {
   4775  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
   4776  1.2  christos 			   line, pos);
   4777  1.2  christos 		return -1;
   4778  1.2  christos 	}
   4779  1.2  christos 
   4780  1.9  christos 	if (check_range && val < (long) data->param2) {
   4781  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
   4782  1.9  christos 			   "min_value=%ld)", line, data->name, val,
   4783  1.2  christos 			   (long) data->param2);
   4784  1.2  christos 		return -1;
   4785  1.2  christos 	}
   4786  1.2  christos 
   4787  1.9  christos 	if (check_range && val > (long) data->param3) {
   4788  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
   4789  1.9  christos 			   "max_value=%ld)", line, data->name, val,
   4790  1.2  christos 			   (long) data->param3);
   4791  1.2  christos 		return -1;
   4792  1.2  christos 	}
   4793  1.2  christos 
   4794  1.9  christos 	same = *dst == val;
   4795  1.9  christos 	*dst = val;
   4796  1.9  christos 
   4797  1.9  christos 	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
   4798  1.9  christos 
   4799  1.9  christos 	return same;
   4800  1.9  christos }
   4801  1.9  christos 
   4802  1.9  christos 
   4803  1.9  christos static int wpa_global_config_parse_int(const struct global_parse_data *data,
   4804  1.9  christos 				       struct wpa_config *config, int line,
   4805  1.9  christos 				       const char *pos)
   4806  1.9  christos {
   4807  1.9  christos 	return wpa_global_config_parse_int_impl(data, config, line, pos, false);
   4808  1.9  christos }
   4809  1.9  christos 
   4810  1.9  christos 
   4811  1.9  christos static int
   4812  1.9  christos wpa_global_config_parse_int_range(const struct global_parse_data *data,
   4813  1.9  christos 				  struct wpa_config *config, int line,
   4814  1.9  christos 				  const char *pos)
   4815  1.9  christos {
   4816  1.9  christos 	return wpa_global_config_parse_int_impl(data, config, line, pos, true);
   4817  1.2  christos }
   4818  1.2  christos 
   4819  1.2  christos 
   4820  1.2  christos static int wpa_global_config_parse_str(const struct global_parse_data *data,
   4821  1.2  christos 				       struct wpa_config *config, int line,
   4822  1.2  christos 				       const char *pos)
   4823  1.2  christos {
   4824  1.9  christos 	size_t len, prev_len;
   4825  1.2  christos 	char **dst, *tmp;
   4826  1.2  christos 
   4827  1.2  christos 	len = os_strlen(pos);
   4828  1.2  christos 	if (data->param2 && len < (size_t) data->param2) {
   4829  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
   4830  1.2  christos 			   "min_len=%ld)", line, data->name,
   4831  1.2  christos 			   (unsigned long) len, (long) data->param2);
   4832  1.2  christos 		return -1;
   4833  1.2  christos 	}
   4834  1.2  christos 
   4835  1.2  christos 	if (data->param3 && len > (size_t) data->param3) {
   4836  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
   4837  1.2  christos 			   "max_len=%ld)", line, data->name,
   4838  1.2  christos 			   (unsigned long) len, (long) data->param3);
   4839  1.2  christos 		return -1;
   4840  1.2  christos 	}
   4841  1.2  christos 
   4842  1.5  christos 	if (has_newline(pos)) {
   4843  1.5  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
   4844  1.5  christos 			   line, data->name);
   4845  1.5  christos 		return -1;
   4846  1.5  christos 	}
   4847  1.5  christos 
   4848  1.9  christos 	dst = (char **) (((u8 *) config) + (long) data->param1);
   4849  1.9  christos 	if (*dst)
   4850  1.9  christos 		prev_len = os_strlen(*dst);
   4851  1.9  christos 	else
   4852  1.9  christos 		prev_len = 0;
   4853  1.9  christos 
   4854  1.9  christos 	/* No change to the previously configured value */
   4855  1.9  christos 	if (*dst && prev_len == len && os_memcmp(*dst, pos, len) == 0)
   4856  1.9  christos 		return 1;
   4857  1.9  christos 
   4858  1.2  christos 	tmp = os_strdup(pos);
   4859  1.2  christos 	if (tmp == NULL)
   4860  1.2  christos 		return -1;
   4861  1.2  christos 
   4862  1.2  christos 	os_free(*dst);
   4863  1.2  christos 	*dst = tmp;
   4864  1.2  christos 	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
   4865  1.2  christos 
   4866  1.2  christos 	return 0;
   4867  1.2  christos }
   4868  1.2  christos 
   4869  1.2  christos 
   4870  1.2  christos static int wpa_config_process_bgscan(const struct global_parse_data *data,
   4871  1.2  christos 				     struct wpa_config *config, int line,
   4872  1.2  christos 				     const char *pos)
   4873  1.2  christos {
   4874  1.2  christos 	size_t len;
   4875  1.2  christos 	char *tmp;
   4876  1.2  christos 	int res;
   4877  1.2  christos 
   4878  1.2  christos 	tmp = wpa_config_parse_string(pos, &len);
   4879  1.2  christos 	if (tmp == NULL) {
   4880  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s",
   4881  1.2  christos 			   line, data->name);
   4882  1.2  christos 		return -1;
   4883  1.2  christos 	}
   4884  1.2  christos 
   4885  1.2  christos 	res = wpa_global_config_parse_str(data, config, line, tmp);
   4886  1.2  christos 	os_free(tmp);
   4887  1.2  christos 	return res;
   4888  1.2  christos }
   4889  1.2  christos 
   4890  1.2  christos 
   4891  1.2  christos static int wpa_global_config_parse_bin(const struct global_parse_data *data,
   4892  1.2  christos 				       struct wpa_config *config, int line,
   4893  1.2  christos 				       const char *pos)
   4894  1.2  christos {
   4895  1.2  christos 	struct wpabuf **dst, *tmp;
   4896  1.2  christos 
   4897  1.6  christos 	tmp = wpabuf_parse_bin(pos);
   4898  1.6  christos 	if (!tmp)
   4899  1.2  christos 		return -1;
   4900  1.2  christos 
   4901  1.2  christos 	dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
   4902  1.9  christos 	if (wpabuf_cmp(*dst, tmp) == 0) {
   4903  1.9  christos 		wpabuf_free(tmp);
   4904  1.9  christos 		return 1;
   4905  1.9  christos 	}
   4906  1.2  christos 	wpabuf_free(*dst);
   4907  1.2  christos 	*dst = tmp;
   4908  1.2  christos 	wpa_printf(MSG_DEBUG, "%s", data->name);
   4909  1.2  christos 
   4910  1.2  christos 	return 0;
   4911  1.2  christos }
   4912  1.2  christos 
   4913  1.2  christos 
   4914  1.2  christos static int wpa_config_process_freq_list(const struct global_parse_data *data,
   4915  1.2  christos 					struct wpa_config *config, int line,
   4916  1.2  christos 					const char *value)
   4917  1.2  christos {
   4918  1.2  christos 	int *freqs;
   4919  1.2  christos 
   4920  1.2  christos 	freqs = wpa_config_parse_int_array(value);
   4921  1.2  christos 	if (freqs == NULL)
   4922  1.2  christos 		return -1;
   4923  1.2  christos 	if (freqs[0] == 0) {
   4924  1.2  christos 		os_free(freqs);
   4925  1.2  christos 		freqs = NULL;
   4926  1.2  christos 	}
   4927  1.2  christos 	os_free(config->freq_list);
   4928  1.2  christos 	config->freq_list = freqs;
   4929  1.2  christos 	return 0;
   4930  1.2  christos }
   4931  1.2  christos 
   4932  1.2  christos 
   4933  1.9  christos static int
   4934  1.9  christos wpa_config_process_initial_freq_list(const struct global_parse_data *data,
   4935  1.9  christos 				     struct wpa_config *config, int line,
   4936  1.9  christos 				     const char *value)
   4937  1.9  christos {
   4938  1.9  christos 	int *freqs;
   4939  1.9  christos 
   4940  1.9  christos 	freqs = wpa_config_parse_int_array(value);
   4941  1.9  christos 	if (!freqs)
   4942  1.9  christos 		return -1;
   4943  1.9  christos 	if (freqs[0] == 0) {
   4944  1.9  christos 		os_free(freqs);
   4945  1.9  christos 		freqs = NULL;
   4946  1.9  christos 	}
   4947  1.9  christos 	os_free(config->initial_freq_list);
   4948  1.9  christos 	config->initial_freq_list = freqs;
   4949  1.9  christos 	return 0;
   4950  1.9  christos }
   4951  1.9  christos 
   4952  1.9  christos 
   4953  1.2  christos #ifdef CONFIG_P2P
   4954  1.2  christos static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
   4955  1.2  christos 					struct wpa_config *config, int line,
   4956  1.2  christos 					const char *pos)
   4957  1.2  christos {
   4958  1.2  christos 	u32 *dst;
   4959  1.2  christos 	struct hostapd_ip_addr addr;
   4960  1.2  christos 
   4961  1.2  christos 	if (hostapd_parse_ip_addr(pos, &addr) < 0)
   4962  1.2  christos 		return -1;
   4963  1.2  christos 	if (addr.af != AF_INET)
   4964  1.2  christos 		return -1;
   4965  1.2  christos 
   4966  1.2  christos 	dst = (u32 *) (((u8 *) config) + (long) data->param1);
   4967  1.9  christos 	if (os_memcmp(dst, &addr.u.v4.s_addr, 4) == 0)
   4968  1.9  christos 		return 1;
   4969  1.2  christos 	os_memcpy(dst, &addr.u.v4.s_addr, 4);
   4970  1.2  christos 	wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name,
   4971  1.2  christos 		   WPA_GET_BE32((u8 *) dst));
   4972  1.2  christos 
   4973  1.2  christos 	return 0;
   4974  1.2  christos }
   4975  1.2  christos #endif /* CONFIG_P2P */
   4976  1.2  christos 
   4977  1.2  christos 
   4978  1.2  christos static int wpa_config_process_country(const struct global_parse_data *data,
   4979  1.2  christos 				      struct wpa_config *config, int line,
   4980  1.2  christos 				      const char *pos)
   4981  1.2  christos {
   4982  1.2  christos 	if (!pos[0] || !pos[1]) {
   4983  1.2  christos 		wpa_printf(MSG_DEBUG, "Invalid country set");
   4984  1.2  christos 		return -1;
   4985  1.2  christos 	}
   4986  1.9  christos 	if (pos[0] == config->country[0] && pos[1] == config->country[1])
   4987  1.9  christos 		return 1;
   4988  1.2  christos 	config->country[0] = pos[0];
   4989  1.2  christos 	config->country[1] = pos[1];
   4990  1.2  christos 	wpa_printf(MSG_DEBUG, "country='%c%c'",
   4991  1.2  christos 		   config->country[0], config->country[1]);
   4992  1.2  christos 	return 0;
   4993  1.2  christos }
   4994  1.2  christos 
   4995  1.2  christos 
   4996  1.9  christos #ifndef CONFIG_NO_LOAD_DYNAMIC_EAP
   4997  1.2  christos static int wpa_config_process_load_dynamic_eap(
   4998  1.2  christos 	const struct global_parse_data *data, struct wpa_config *config,
   4999  1.2  christos 	int line, const char *so)
   5000  1.2  christos {
   5001  1.2  christos 	int ret;
   5002  1.2  christos 	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
   5003  1.2  christos 	ret = eap_peer_method_load(so);
   5004  1.2  christos 	if (ret == -2) {
   5005  1.2  christos 		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
   5006  1.2  christos 			   "reloading.");
   5007  1.2  christos 	} else if (ret) {
   5008  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
   5009  1.2  christos 			   "method '%s'.", line, so);
   5010  1.2  christos 		return -1;
   5011  1.2  christos 	}
   5012  1.2  christos 
   5013  1.2  christos 	return 0;
   5014  1.2  christos }
   5015  1.9  christos #endif /* CONFIG_NO_LOAD_DYNAMIC_EAP */
   5016  1.2  christos 
   5017  1.2  christos 
   5018  1.2  christos #ifdef CONFIG_WPS
   5019  1.2  christos 
   5020  1.2  christos static int wpa_config_process_uuid(const struct global_parse_data *data,
   5021  1.2  christos 				   struct wpa_config *config, int line,
   5022  1.2  christos 				   const char *pos)
   5023  1.2  christos {
   5024  1.2  christos 	char buf[40];
   5025  1.2  christos 	if (uuid_str2bin(pos, config->uuid)) {
   5026  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
   5027  1.2  christos 		return -1;
   5028  1.2  christos 	}
   5029  1.2  christos 	uuid_bin2str(config->uuid, buf, sizeof(buf));
   5030  1.2  christos 	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
   5031  1.2  christos 	return 0;
   5032  1.2  christos }
   5033  1.2  christos 
   5034  1.2  christos 
   5035  1.2  christos static int wpa_config_process_device_type(
   5036  1.2  christos 	const struct global_parse_data *data,
   5037  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5038  1.2  christos {
   5039  1.2  christos 	return wps_dev_type_str2bin(pos, config->device_type);
   5040  1.2  christos }
   5041  1.2  christos 
   5042  1.2  christos 
   5043  1.2  christos static int wpa_config_process_os_version(const struct global_parse_data *data,
   5044  1.2  christos 					 struct wpa_config *config, int line,
   5045  1.2  christos 					 const char *pos)
   5046  1.2  christos {
   5047  1.2  christos 	if (hexstr2bin(pos, config->os_version, 4)) {
   5048  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
   5049  1.2  christos 		return -1;
   5050  1.2  christos 	}
   5051  1.2  christos 	wpa_printf(MSG_DEBUG, "os_version=%08x",
   5052  1.2  christos 		   WPA_GET_BE32(config->os_version));
   5053  1.2  christos 	return 0;
   5054  1.2  christos }
   5055  1.2  christos 
   5056  1.2  christos 
   5057  1.2  christos static int wpa_config_process_wps_vendor_ext_m1(
   5058  1.2  christos 	const struct global_parse_data *data,
   5059  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5060  1.2  christos {
   5061  1.2  christos 	struct wpabuf *tmp;
   5062  1.2  christos 	int len = os_strlen(pos) / 2;
   5063  1.2  christos 	u8 *p;
   5064  1.2  christos 
   5065  1.2  christos 	if (!len) {
   5066  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: "
   5067  1.2  christos 			   "invalid wps_vendor_ext_m1", line);
   5068  1.2  christos 		return -1;
   5069  1.2  christos 	}
   5070  1.2  christos 
   5071  1.2  christos 	tmp = wpabuf_alloc(len);
   5072  1.2  christos 	if (tmp) {
   5073  1.2  christos 		p = wpabuf_put(tmp, len);
   5074  1.2  christos 
   5075  1.2  christos 		if (hexstr2bin(pos, p, len)) {
   5076  1.2  christos 			wpa_printf(MSG_ERROR, "Line %d: "
   5077  1.2  christos 				   "invalid wps_vendor_ext_m1", line);
   5078  1.2  christos 			wpabuf_free(tmp);
   5079  1.2  christos 			return -1;
   5080  1.2  christos 		}
   5081  1.2  christos 
   5082  1.2  christos 		wpabuf_free(config->wps_vendor_ext_m1);
   5083  1.2  christos 		config->wps_vendor_ext_m1 = tmp;
   5084  1.2  christos 	} else {
   5085  1.2  christos 		wpa_printf(MSG_ERROR, "Can not allocate "
   5086  1.2  christos 			   "memory for wps_vendor_ext_m1");
   5087  1.2  christos 		return -1;
   5088  1.2  christos 	}
   5089  1.2  christos 
   5090  1.2  christos 	return 0;
   5091  1.2  christos }
   5092  1.2  christos 
   5093  1.2  christos #endif /* CONFIG_WPS */
   5094  1.2  christos 
   5095  1.2  christos #ifdef CONFIG_P2P
   5096  1.2  christos static int wpa_config_process_sec_device_type(
   5097  1.2  christos 	const struct global_parse_data *data,
   5098  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5099  1.2  christos {
   5100  1.2  christos 	int idx;
   5101  1.2  christos 
   5102  1.2  christos 	if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
   5103  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
   5104  1.2  christos 			   "items", line);
   5105  1.2  christos 		return -1;
   5106  1.2  christos 	}
   5107  1.2  christos 
   5108  1.2  christos 	idx = config->num_sec_device_types;
   5109  1.2  christos 
   5110  1.2  christos 	if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
   5111  1.2  christos 		return -1;
   5112  1.2  christos 
   5113  1.2  christos 	config->num_sec_device_types++;
   5114  1.2  christos 	return 0;
   5115  1.2  christos }
   5116  1.2  christos 
   5117  1.2  christos 
   5118  1.2  christos static int wpa_config_process_p2p_pref_chan(
   5119  1.2  christos 	const struct global_parse_data *data,
   5120  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5121  1.2  christos {
   5122  1.2  christos 	struct p2p_channel *pref = NULL, *n;
   5123  1.9  christos 	size_t num = 0;
   5124  1.2  christos 	const char *pos2;
   5125  1.2  christos 	u8 op_class, chan;
   5126  1.2  christos 
   5127  1.2  christos 	/* format: class:chan,class:chan,... */
   5128  1.2  christos 
   5129  1.2  christos 	while (*pos) {
   5130  1.2  christos 		op_class = atoi(pos);
   5131  1.2  christos 		pos2 = os_strchr(pos, ':');
   5132  1.2  christos 		if (pos2 == NULL)
   5133  1.2  christos 			goto fail;
   5134  1.2  christos 		pos2++;
   5135  1.2  christos 		chan = atoi(pos2);
   5136  1.2  christos 
   5137  1.2  christos 		n = os_realloc_array(pref, num + 1,
   5138  1.2  christos 				     sizeof(struct p2p_channel));
   5139  1.2  christos 		if (n == NULL)
   5140  1.2  christos 			goto fail;
   5141  1.2  christos 		pref = n;
   5142  1.2  christos 		pref[num].op_class = op_class;
   5143  1.2  christos 		pref[num].chan = chan;
   5144  1.2  christos 		num++;
   5145  1.2  christos 
   5146  1.2  christos 		pos = os_strchr(pos2, ',');
   5147  1.2  christos 		if (pos == NULL)
   5148  1.2  christos 			break;
   5149  1.2  christos 		pos++;
   5150  1.2  christos 	}
   5151  1.2  christos 
   5152  1.2  christos 	os_free(config->p2p_pref_chan);
   5153  1.2  christos 	config->p2p_pref_chan = pref;
   5154  1.2  christos 	config->num_p2p_pref_chan = num;
   5155  1.2  christos 	wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs",
   5156  1.2  christos 		    (u8 *) config->p2p_pref_chan,
   5157  1.2  christos 		    config->num_p2p_pref_chan * sizeof(struct p2p_channel));
   5158  1.2  christos 
   5159  1.2  christos 	return 0;
   5160  1.2  christos 
   5161  1.2  christos fail:
   5162  1.2  christos 	os_free(pref);
   5163  1.2  christos 	wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line);
   5164  1.2  christos 	return -1;
   5165  1.2  christos }
   5166  1.2  christos 
   5167  1.2  christos 
   5168  1.2  christos static int wpa_config_process_p2p_no_go_freq(
   5169  1.2  christos 	const struct global_parse_data *data,
   5170  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5171  1.2  christos {
   5172  1.2  christos 	int ret;
   5173  1.2  christos 
   5174  1.2  christos 	ret = freq_range_list_parse(&config->p2p_no_go_freq, pos);
   5175  1.2  christos 	if (ret < 0) {
   5176  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_no_go_freq", line);
   5177  1.2  christos 		return -1;
   5178  1.2  christos 	}
   5179  1.2  christos 
   5180  1.2  christos 	wpa_printf(MSG_DEBUG, "P2P: p2p_no_go_freq with %u items",
   5181  1.2  christos 		   config->p2p_no_go_freq.num);
   5182  1.2  christos 
   5183  1.2  christos 	return 0;
   5184  1.2  christos }
   5185  1.2  christos 
   5186  1.8  christos 
   5187  1.8  christos static int wpa_config_process_p2p_device_persistent_mac_addr(
   5188  1.8  christos 	const struct global_parse_data *data,
   5189  1.8  christos 	struct wpa_config *config, int line, const char *pos)
   5190  1.8  christos {
   5191  1.8  christos 	if (hwaddr_aton2(pos, config->p2p_device_persistent_mac_addr) < 0) {
   5192  1.8  christos 		wpa_printf(MSG_ERROR,
   5193  1.8  christos 			   "Line %d: Invalid p2p_device_persistent_mac_addr '%s'",
   5194  1.8  christos 			   line, pos);
   5195  1.8  christos 		return -1;
   5196  1.8  christos 	}
   5197  1.8  christos 
   5198  1.8  christos 	return 0;
   5199  1.8  christos }
   5200  1.8  christos 
   5201  1.2  christos #endif /* CONFIG_P2P */
   5202  1.2  christos 
   5203  1.2  christos 
   5204  1.2  christos static int wpa_config_process_hessid(
   5205  1.2  christos 	const struct global_parse_data *data,
   5206  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5207  1.2  christos {
   5208  1.2  christos 	if (hwaddr_aton2(pos, config->hessid) < 0) {
   5209  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
   5210  1.2  christos 			   line, pos);
   5211  1.2  christos 		return -1;
   5212  1.2  christos 	}
   5213  1.2  christos 
   5214  1.2  christos 	return 0;
   5215  1.2  christos }
   5216  1.2  christos 
   5217  1.2  christos 
   5218  1.2  christos static int wpa_config_process_sae_groups(
   5219  1.2  christos 	const struct global_parse_data *data,
   5220  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5221  1.2  christos {
   5222  1.2  christos 	int *groups = wpa_config_parse_int_array(pos);
   5223  1.2  christos 	if (groups == NULL) {
   5224  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'",
   5225  1.2  christos 			   line, pos);
   5226  1.2  christos 		return -1;
   5227  1.2  christos 	}
   5228  1.2  christos 
   5229  1.2  christos 	os_free(config->sae_groups);
   5230  1.2  christos 	config->sae_groups = groups;
   5231  1.2  christos 
   5232  1.2  christos 	return 0;
   5233  1.2  christos }
   5234  1.2  christos 
   5235  1.2  christos 
   5236  1.2  christos static int wpa_config_process_ap_vendor_elements(
   5237  1.2  christos 	const struct global_parse_data *data,
   5238  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5239  1.2  christos {
   5240  1.2  christos 	struct wpabuf *tmp;
   5241  1.2  christos 
   5242  1.9  christos 	if (!*pos) {
   5243  1.9  christos 		wpabuf_free(config->ap_vendor_elements);
   5244  1.9  christos 		config->ap_vendor_elements = NULL;
   5245  1.9  christos 		return 0;
   5246  1.9  christos 	}
   5247  1.9  christos 
   5248  1.9  christos 	tmp = wpabuf_parse_bin(pos);
   5249  1.9  christos 	if (!tmp) {
   5250  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
   5251  1.2  christos 			   line);
   5252  1.2  christos 		return -1;
   5253  1.2  christos 	}
   5254  1.9  christos 	wpabuf_free(config->ap_vendor_elements);
   5255  1.9  christos 	config->ap_vendor_elements = tmp;
   5256  1.9  christos 
   5257  1.9  christos 	return 0;
   5258  1.9  christos }
   5259  1.9  christos 
   5260  1.2  christos 
   5261  1.9  christos static int wpa_config_process_ap_assocresp_elements(
   5262  1.9  christos 	const struct global_parse_data *data,
   5263  1.9  christos 	struct wpa_config *config, int line, const char *pos)
   5264  1.9  christos {
   5265  1.9  christos 	struct wpabuf *tmp;
   5266  1.2  christos 
   5267  1.9  christos 	if (!*pos) {
   5268  1.9  christos 		wpabuf_free(config->ap_assocresp_elements);
   5269  1.9  christos 		config->ap_assocresp_elements = NULL;
   5270  1.9  christos 		return 0;
   5271  1.9  christos 	}
   5272  1.2  christos 
   5273  1.9  christos 	tmp = wpabuf_parse_bin(pos);
   5274  1.9  christos 	if (!tmp) {
   5275  1.9  christos 		wpa_printf(MSG_ERROR, "Line %d: invalid ap_assocresp_elements",
   5276  1.9  christos 			   line);
   5277  1.2  christos 		return -1;
   5278  1.2  christos 	}
   5279  1.9  christos 	wpabuf_free(config->ap_assocresp_elements);
   5280  1.9  christos 	config->ap_assocresp_elements = tmp;
   5281  1.2  christos 
   5282  1.2  christos 	return 0;
   5283  1.2  christos }
   5284  1.2  christos 
   5285  1.2  christos 
   5286  1.2  christos #ifdef CONFIG_CTRL_IFACE
   5287  1.2  christos static int wpa_config_process_no_ctrl_interface(
   5288  1.2  christos 	const struct global_parse_data *data,
   5289  1.2  christos 	struct wpa_config *config, int line, const char *pos)
   5290  1.2  christos {
   5291  1.2  christos 	wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL");
   5292  1.2  christos 	os_free(config->ctrl_interface);
   5293  1.2  christos 	config->ctrl_interface = NULL;
   5294  1.2  christos 	return 0;
   5295  1.2  christos }
   5296  1.2  christos #endif /* CONFIG_CTRL_IFACE */
   5297  1.2  christos 
   5298  1.2  christos 
   5299  1.2  christos static int wpa_config_get_int(const char *name, struct wpa_config *config,
   5300  1.2  christos 			      long offset, char *buf, size_t buflen,
   5301  1.2  christos 			      int pretty_print)
   5302  1.2  christos {
   5303  1.2  christos 	int *val = (int *) (((u8 *) config) + (long) offset);
   5304  1.2  christos 
   5305  1.2  christos 	if (pretty_print)
   5306  1.2  christos 		return os_snprintf(buf, buflen, "%s=%d\n", name, *val);
   5307  1.2  christos 	return os_snprintf(buf, buflen, "%d", *val);
   5308  1.2  christos }
   5309  1.2  christos 
   5310  1.2  christos 
   5311  1.2  christos static int wpa_config_get_str(const char *name, struct wpa_config *config,
   5312  1.2  christos 			      long offset, char *buf, size_t buflen,
   5313  1.2  christos 			      int pretty_print)
   5314  1.2  christos {
   5315  1.2  christos 	char **val = (char **) (((u8 *) config) + (long) offset);
   5316  1.2  christos 	int res;
   5317  1.2  christos 
   5318  1.2  christos 	if (pretty_print)
   5319  1.2  christos 		res = os_snprintf(buf, buflen, "%s=%s\n", name,
   5320  1.2  christos 				  *val ? *val : "null");
   5321  1.2  christos 	else if (!*val)
   5322  1.2  christos 		return -1;
   5323  1.2  christos 	else
   5324  1.2  christos 		res = os_snprintf(buf, buflen, "%s", *val);
   5325  1.2  christos 	if (os_snprintf_error(buflen, res))
   5326  1.2  christos 		res = -1;
   5327  1.2  christos 
   5328  1.2  christos 	return res;
   5329  1.2  christos }
   5330  1.2  christos 
   5331  1.2  christos 
   5332  1.6  christos #ifdef CONFIG_P2P
   5333  1.6  christos static int wpa_config_get_ipv4(const char *name, struct wpa_config *config,
   5334  1.6  christos 			       long offset, char *buf, size_t buflen,
   5335  1.6  christos 			       int pretty_print)
   5336  1.6  christos {
   5337  1.6  christos 	void *val = ((u8 *) config) + (long) offset;
   5338  1.6  christos 	int res;
   5339  1.6  christos 	char addr[INET_ADDRSTRLEN];
   5340  1.6  christos 
   5341  1.6  christos 	if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr)))
   5342  1.6  christos 		return -1;
   5343  1.6  christos 
   5344  1.6  christos 	if (pretty_print)
   5345  1.6  christos 		res = os_snprintf(buf, buflen, "%s=%s\n", name, addr);
   5346  1.6  christos 	else
   5347  1.6  christos 		res = os_snprintf(buf, buflen, "%s", addr);
   5348  1.6  christos 
   5349  1.6  christos 	if (os_snprintf_error(buflen, res))
   5350  1.6  christos 		res = -1;
   5351  1.6  christos 
   5352  1.6  christos 	return res;
   5353  1.6  christos }
   5354  1.6  christos #endif /* CONFIG_P2P */
   5355  1.6  christos 
   5356  1.6  christos 
   5357  1.9  christos #ifdef CONFIG_TESTING_OPTIONS
   5358  1.9  christos static int wpa_config_process_mld_connect_bssid_pref(
   5359  1.9  christos 	const struct global_parse_data *data,
   5360  1.9  christos 	struct wpa_config *config, int line, const char *pos)
   5361  1.9  christos {
   5362  1.9  christos 	if (hwaddr_aton2(pos, config->mld_connect_bssid_pref) < 0) {
   5363  1.9  christos 		wpa_printf(MSG_ERROR,
   5364  1.9  christos 			   "Line %d: Invalid mld_connect_bssid_pref '%s'",
   5365  1.9  christos 			   line, pos);
   5366  1.9  christos 		return -1;
   5367  1.9  christos 	}
   5368  1.9  christos 
   5369  1.9  christos 	return 0;
   5370  1.9  christos }
   5371  1.9  christos #endif /* CONFIG_TESTING_OPTIONS */
   5372  1.9  christos 
   5373  1.9  christos 
   5374  1.2  christos #ifdef OFFSET
   5375  1.2  christos #undef OFFSET
   5376  1.2  christos #endif /* OFFSET */
   5377  1.2  christos /* OFFSET: Get offset of a variable within the wpa_config structure */
   5378  1.2  christos #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
   5379  1.2  christos 
   5380  1.2  christos #define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL
   5381  1.2  christos #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL
   5382  1.2  christos #define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f)
   5383  1.2  christos #define INT(f) _INT(f), NULL, NULL
   5384  1.9  christos #define INT_RANGE(f, min, max) #f, wpa_global_config_parse_int_range, \
   5385  1.9  christos 	wpa_config_get_int, OFFSET(f), (void *) min, (void *) max
   5386  1.2  christos #define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f)
   5387  1.2  christos #define STR(f) _STR(f), NULL, NULL
   5388  1.2  christos #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
   5389  1.2  christos #define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL
   5390  1.6  christos #define IPV4(f) #f, wpa_global_config_parse_ipv4, wpa_config_get_ipv4,  \
   5391  1.6  christos 	OFFSET(f), NULL, NULL
   5392  1.2  christos 
   5393  1.2  christos static const struct global_parse_data global_fields[] = {
   5394  1.2  christos #ifdef CONFIG_CTRL_IFACE
   5395  1.2  christos 	{ STR(ctrl_interface), 0 },
   5396  1.2  christos 	{ FUNC_NO_VAR(no_ctrl_interface), 0 },
   5397  1.2  christos 	{ STR(ctrl_interface_group), 0 } /* deprecated */,
   5398  1.2  christos #endif /* CONFIG_CTRL_IFACE */
   5399  1.2  christos #ifdef CONFIG_MACSEC
   5400  1.2  christos 	{ INT_RANGE(eapol_version, 1, 3), 0 },
   5401  1.2  christos #else /* CONFIG_MACSEC */
   5402  1.2  christos 	{ INT_RANGE(eapol_version, 1, 2), 0 },
   5403  1.2  christos #endif /* CONFIG_MACSEC */
   5404  1.2  christos 	{ INT(ap_scan), 0 },
   5405  1.9  christos 	{ FUNC(bgscan), CFG_CHANGED_BGSCAN },
   5406  1.2  christos #ifdef CONFIG_MESH
   5407  1.2  christos 	{ INT(user_mpm), 0 },
   5408  1.2  christos 	{ INT_RANGE(max_peer_links, 0, 255), 0 },
   5409  1.2  christos 	{ INT(mesh_max_inactivity), 0 },
   5410  1.9  christos 	{ INT_RANGE(mesh_fwding, 0, 1), 0 },
   5411  1.6  christos 	{ INT(dot11RSNASAERetransPeriod), 0 },
   5412  1.2  christos #endif /* CONFIG_MESH */
   5413  1.2  christos 	{ INT(disable_scan_offload), 0 },
   5414  1.2  christos 	{ INT(fast_reauth), 0 },
   5415  1.9  christos #ifndef CONFIG_OPENSC_ENGINE_PATH
   5416  1.2  christos 	{ STR(opensc_engine_path), 0 },
   5417  1.9  christos #endif /* CONFIG_OPENSC_ENGINE_PATH */
   5418  1.9  christos #ifndef CONFIG_PKCS11_ENGINE_PATH
   5419  1.2  christos 	{ STR(pkcs11_engine_path), 0 },
   5420  1.9  christos #endif /* CONFIG_PKCS11_ENGINE_PATH */
   5421  1.9  christos #ifndef CONFIG_PKCS11_MODULE_PATH
   5422  1.2  christos 	{ STR(pkcs11_module_path), 0 },
   5423  1.9  christos #endif /* CONFIG_PKCS11_MODULE_PATH */
   5424  1.2  christos 	{ STR(openssl_ciphers), 0 },
   5425  1.2  christos 	{ STR(pcsc_reader), 0 },
   5426  1.2  christos 	{ STR(pcsc_pin), 0 },
   5427  1.2  christos 	{ INT(external_sim), 0 },
   5428  1.2  christos 	{ STR(driver_param), 0 },
   5429  1.2  christos 	{ INT(dot11RSNAConfigPMKLifetime), 0 },
   5430  1.2  christos 	{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
   5431  1.2  christos 	{ INT(dot11RSNAConfigSATimeout), 0 },
   5432  1.2  christos #ifndef CONFIG_NO_CONFIG_WRITE
   5433  1.2  christos 	{ INT(update_config), 0 },
   5434  1.2  christos #endif /* CONFIG_NO_CONFIG_WRITE */
   5435  1.9  christos #ifndef CONFIG_NO_LOAD_DYNAMIC_EAP
   5436  1.2  christos 	{ FUNC_NO_VAR(load_dynamic_eap), 0 },
   5437  1.9  christos #endif /* CONFIG_NO_LOAD_DYNAMIC_EAP */
   5438  1.2  christos #ifdef CONFIG_WPS
   5439  1.2  christos 	{ FUNC(uuid), CFG_CHANGED_UUID },
   5440  1.7  christos 	{ INT_RANGE(auto_uuid, 0, 1), 0 },
   5441  1.6  christos 	{ STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN),
   5442  1.6  christos 	  CFG_CHANGED_DEVICE_NAME },
   5443  1.2  christos 	{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
   5444  1.2  christos 	{ STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
   5445  1.2  christos 	{ STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
   5446  1.2  christos 	{ STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
   5447  1.2  christos 	{ FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
   5448  1.2  christos 	{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
   5449  1.2  christos 	{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
   5450  1.2  christos 	{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
   5451  1.8  christos 	{ INT_RANGE(wps_cred_add_sae, 0, 1), 0 },
   5452  1.2  christos 	{ FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
   5453  1.2  christos #endif /* CONFIG_WPS */
   5454  1.2  christos #ifdef CONFIG_P2P
   5455  1.2  christos 	{ FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
   5456  1.6  christos 	{ INT(p2p_listen_reg_class), CFG_CHANGED_P2P_LISTEN_CHANNEL },
   5457  1.6  christos 	{ INT(p2p_listen_channel), CFG_CHANGED_P2P_LISTEN_CHANNEL },
   5458  1.2  christos 	{ INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL },
   5459  1.2  christos 	{ INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL },
   5460  1.2  christos 	{ INT_RANGE(p2p_go_intent, 0, 15), 0 },
   5461  1.2  christos 	{ STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
   5462  1.2  christos 	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
   5463  1.2  christos 	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
   5464  1.2  christos 	{ INT(p2p_group_idle), 0 },
   5465  1.6  christos 	{ INT_RANGE(p2p_go_freq_change_policy, 0, P2P_GO_FREQ_MOVE_MAX), 0 },
   5466  1.2  christos 	{ INT_RANGE(p2p_passphrase_len, 8, 63),
   5467  1.2  christos 	  CFG_CHANGED_P2P_PASSPHRASE_LEN },
   5468  1.2  christos 	{ FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
   5469  1.2  christos 	{ FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN },
   5470  1.2  christos 	{ INT_RANGE(p2p_add_cli_chan, 0, 1), 0 },
   5471  1.2  christos 	{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
   5472  1.2  christos 	{ INT(p2p_go_ht40), 0 },
   5473  1.2  christos 	{ INT(p2p_go_vht), 0 },
   5474  1.8  christos 	{ INT(p2p_go_he), 0 },
   5475  1.9  christos 	{ INT(p2p_go_edmg), 0 },
   5476  1.2  christos 	{ INT(p2p_disabled), 0 },
   5477  1.2  christos 	{ INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
   5478  1.2  christos 	{ INT(p2p_no_group_iface), 0 },
   5479  1.2  christos 	{ INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
   5480  1.2  christos 	{ IPV4(ip_addr_go), 0 },
   5481  1.2  christos 	{ IPV4(ip_addr_mask), 0 },
   5482  1.2  christos 	{ IPV4(ip_addr_start), 0 },
   5483  1.2  christos 	{ IPV4(ip_addr_end), 0 },
   5484  1.6  christos 	{ INT_RANGE(p2p_cli_probe, 0, 1), 0 },
   5485  1.8  christos 	{ INT(p2p_device_random_mac_addr), 0 },
   5486  1.8  christos 	{ FUNC(p2p_device_persistent_mac_addr), 0 },
   5487  1.8  christos 	{ INT(p2p_interface_random_mac_addr), 0 },
   5488  1.9  christos 	{ INT(p2p_6ghz_disable), 0 },
   5489  1.2  christos #endif /* CONFIG_P2P */
   5490  1.2  christos 	{ FUNC(country), CFG_CHANGED_COUNTRY },
   5491  1.2  christos 	{ INT(bss_max_count), 0 },
   5492  1.2  christos 	{ INT(bss_expiration_age), 0 },
   5493  1.2  christos 	{ INT(bss_expiration_scan_count), 0 },
   5494  1.2  christos 	{ INT_RANGE(filter_ssids, 0, 1), 0 },
   5495  1.2  christos 	{ INT_RANGE(filter_rssi, -100, 0), 0 },
   5496  1.2  christos 	{ INT(max_num_sta), 0 },
   5497  1.7  christos 	{ INT_RANGE(ap_isolate, 0, 1), 0 },
   5498  1.2  christos 	{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
   5499  1.2  christos #ifdef CONFIG_HS20
   5500  1.2  christos 	{ INT_RANGE(hs20, 0, 1), 0 },
   5501  1.2  christos #endif /* CONFIG_HS20 */
   5502  1.2  christos 	{ INT_RANGE(interworking, 0, 1), 0 },
   5503  1.2  christos 	{ FUNC(hessid), 0 },
   5504  1.2  christos 	{ INT_RANGE(access_network_type, 0, 15), 0 },
   5505  1.7  christos 	{ INT_RANGE(go_interworking, 0, 1), 0 },
   5506  1.7  christos 	{ INT_RANGE(go_access_network_type, 0, 15), 0 },
   5507  1.7  christos 	{ INT_RANGE(go_internet, 0, 1), 0 },
   5508  1.7  christos 	{ INT_RANGE(go_venue_group, 0, 255), 0 },
   5509  1.7  christos 	{ INT_RANGE(go_venue_type, 0, 255), 0 },
   5510  1.2  christos 	{ INT_RANGE(pbc_in_m1, 0, 1), 0 },
   5511  1.2  christos 	{ STR(autoscan), 0 },
   5512  1.2  christos 	{ INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
   5513  1.2  christos 	  CFG_CHANGED_NFC_PASSWORD_TOKEN },
   5514  1.2  christos 	{ BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
   5515  1.2  christos 	{ BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
   5516  1.2  christos 	{ BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN },
   5517  1.2  christos 	{ STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
   5518  1.2  christos 	{ INT(p2p_go_max_inactivity), 0 },
   5519  1.2  christos 	{ INT_RANGE(auto_interworking, 0, 1), 0 },
   5520  1.2  christos 	{ INT(okc), 0 },
   5521  1.2  christos 	{ INT(pmf), 0 },
   5522  1.9  christos 	{ INT_RANGE(sae_check_mfp, 0, 1), 0 },
   5523  1.2  christos 	{ FUNC(sae_groups), 0 },
   5524  1.9  christos 	{ INT_RANGE(sae_pwe, 0, 3), 0 },
   5525  1.9  christos 	{ INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 },
   5526  1.2  christos 	{ INT(dtim_period), 0 },
   5527  1.2  christos 	{ INT(beacon_int), 0 },
   5528  1.9  christos 	{ FUNC(ap_assocresp_elements), 0 },
   5529  1.2  christos 	{ FUNC(ap_vendor_elements), 0 },
   5530  1.2  christos 	{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
   5531  1.2  christos 	{ FUNC(freq_list), 0 },
   5532  1.9  christos 	{ FUNC(initial_freq_list), 0},
   5533  1.2  christos 	{ INT(scan_cur_freq), 0 },
   5534  1.9  christos 	{ INT(scan_res_valid_for_connect), 0},
   5535  1.2  christos 	{ INT(sched_scan_interval), 0 },
   5536  1.7  christos 	{ INT(sched_scan_start_delay), 0 },
   5537  1.2  christos 	{ INT(tdls_external_control), 0},
   5538  1.2  christos 	{ STR(osu_dir), 0 },
   5539  1.7  christos 	{ STR(wowlan_triggers), CFG_CHANGED_WOWLAN_TRIGGERS },
   5540  1.2  christos 	{ INT(p2p_search_delay), 0},
   5541  1.9  christos 	{ INT_RANGE(mac_addr, 0, 2), 0 },
   5542  1.2  christos 	{ INT(rand_addr_lifetime), 0 },
   5543  1.9  christos 	{ INT_RANGE(preassoc_mac_addr, 0, 2), 0 },
   5544  1.2  christos 	{ INT(key_mgmt_offload), 0},
   5545  1.2  christos 	{ INT(passive_scan), 0 },
   5546  1.2  christos 	{ INT(reassoc_same_bss_optim), 0 },
   5547  1.6  christos 	{ INT(wps_priority), 0},
   5548  1.6  christos #ifdef CONFIG_FST
   5549  1.6  christos 	{ STR_RANGE(fst_group_id, 1, FST_MAX_GROUP_ID_LEN), 0 },
   5550  1.6  christos 	{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
   5551  1.6  christos 	{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
   5552  1.6  christos #endif /* CONFIG_FST */
   5553  1.7  christos 	{ INT_RANGE(cert_in_cb, 0, 1), 0 },
   5554  1.6  christos 	{ INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
   5555  1.6  christos 	{ STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS },
   5556  1.6  christos #ifdef CONFIG_MBO
   5557  1.6  christos 	{ STR(non_pref_chan), 0 },
   5558  1.6  christos 	{ INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE,
   5559  1.6  christos 		    MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
   5560  1.7  christos 	{ INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 },
   5561  1.7  christos 	{ INT_RANGE(oce, 0, 3), 0 },
   5562  1.7  christos #endif /* CONFIG_MBO */
   5563  1.6  christos 	{ INT(gas_address3), 0 },
   5564  1.6  christos 	{ INT_RANGE(ftm_responder, 0, 1), 0 },
   5565  1.6  christos 	{ INT_RANGE(ftm_initiator, 0, 1), 0 },
   5566  1.7  christos 	{ INT(gas_rand_addr_lifetime), 0 },
   5567  1.7  christos 	{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
   5568  1.9  christos #ifdef CONFIG_DPP
   5569  1.7  christos 	{ INT_RANGE(dpp_config_processing, 0, 2), 0 },
   5570  1.9  christos 	{ STR(dpp_name), 0 },
   5571  1.9  christos 	{ STR(dpp_mud_url), 0 },
   5572  1.9  christos 	{ STR(dpp_extra_conf_req_name), 0 },
   5573  1.9  christos 	{ STR(dpp_extra_conf_req_value), 0 },
   5574  1.9  christos 	{ INT_RANGE(dpp_connector_privacy_default, 0, 1), 0 },
   5575  1.9  christos #endif /* CONFIG_DPP */
   5576  1.7  christos 	{ INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
   5577  1.8  christos #ifdef CONFIG_WNM
   5578  1.8  christos 	{ INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
   5579  1.9  christos 	{ INT_RANGE(extended_key_id, 0, 1), 0 },
   5580  1.8  christos #endif /* CONFIG_WNM */
   5581  1.9  christos 	{ INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
   5582  1.9  christos #ifdef CONFIG_PASN
   5583  1.9  christos #ifdef CONFIG_TESTING_OPTIONS
   5584  1.9  christos 	{ INT_RANGE(force_kdk_derivation, 0, 1), 0 },
   5585  1.9  christos 	{ INT_RANGE(pasn_corrupt_mic, 0, 1), 0 },
   5586  1.9  christos #endif /* CONFIG_TESTING_OPTIONS */
   5587  1.9  christos #endif /* CONFIG_PASN */
   5588  1.9  christos #ifdef CONFIG_TESTING_OPTIONS
   5589  1.9  christos 	{ INT_RANGE(mld_force_single_link, 0, 1), 0 },
   5590  1.9  christos 	{ INT_RANGE(mld_connect_band_pref, 0, MLD_CONNECT_BAND_PREF_MAX), 0 },
   5591  1.9  christos 	{ FUNC(mld_connect_bssid_pref), 0 },
   5592  1.9  christos #endif /* CONFIG_TESTING_OPTIONS */
   5593  1.9  christos 	{ INT_RANGE(ft_prepend_pmkid, 0, 1), CFG_CHANGED_FT_PREPEND_PMKID },
   5594  1.9  christos 	/* NOTE: When adding new parameters here, add_interface() in
   5595  1.9  christos 	 * wpa_supplicant/dbus_new_introspect.c may need to be modified to
   5596  1.9  christos 	 * increase the size of the iface->xml buffer. */
   5597  1.2  christos };
   5598  1.2  christos 
   5599  1.2  christos #undef FUNC
   5600  1.2  christos #undef _INT
   5601  1.2  christos #undef INT
   5602  1.2  christos #undef INT_RANGE
   5603  1.2  christos #undef _STR
   5604  1.2  christos #undef STR
   5605  1.2  christos #undef STR_RANGE
   5606  1.2  christos #undef BIN
   5607  1.2  christos #undef IPV4
   5608  1.2  christos #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields)
   5609  1.2  christos 
   5610  1.2  christos 
   5611  1.2  christos int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen)
   5612  1.2  christos {
   5613  1.2  christos 	int result = 0;
   5614  1.2  christos 	size_t i;
   5615  1.2  christos 
   5616  1.2  christos 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   5617  1.2  christos 		const struct global_parse_data *field = &global_fields[i];
   5618  1.2  christos 		int tmp;
   5619  1.2  christos 
   5620  1.2  christos 		if (!field->get)
   5621  1.2  christos 			continue;
   5622  1.2  christos 
   5623  1.2  christos 		tmp = field->get(field->name, config, (long) field->param1,
   5624  1.2  christos 				 buf, buflen, 1);
   5625  1.2  christos 		if (tmp < 0)
   5626  1.2  christos 			return -1;
   5627  1.2  christos 		buf += tmp;
   5628  1.2  christos 		buflen -= tmp;
   5629  1.2  christos 		result += tmp;
   5630  1.2  christos 	}
   5631  1.2  christos 	return result;
   5632  1.2  christos }
   5633  1.2  christos 
   5634  1.2  christos 
   5635  1.2  christos int wpa_config_get_value(const char *name, struct wpa_config *config,
   5636  1.2  christos 			 char *buf, size_t buflen)
   5637  1.2  christos {
   5638  1.2  christos 	size_t i;
   5639  1.2  christos 
   5640  1.2  christos 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   5641  1.2  christos 		const struct global_parse_data *field = &global_fields[i];
   5642  1.2  christos 
   5643  1.2  christos 		if (os_strcmp(name, field->name) != 0)
   5644  1.2  christos 			continue;
   5645  1.2  christos 		if (!field->get)
   5646  1.2  christos 			break;
   5647  1.2  christos 		return field->get(name, config, (long) field->param1,
   5648  1.2  christos 				  buf, buflen, 0);
   5649  1.2  christos 	}
   5650  1.2  christos 
   5651  1.2  christos 	return -1;
   5652  1.2  christos }
   5653  1.2  christos 
   5654  1.2  christos 
   5655  1.6  christos int wpa_config_get_num_global_field_names(void)
   5656  1.6  christos {
   5657  1.6  christos 	return NUM_GLOBAL_FIELDS;
   5658  1.6  christos }
   5659  1.6  christos 
   5660  1.6  christos 
   5661  1.6  christos const char * wpa_config_get_global_field_name(unsigned int i, int *no_var)
   5662  1.6  christos {
   5663  1.6  christos 	if (i >= NUM_GLOBAL_FIELDS)
   5664  1.6  christos 		return NULL;
   5665  1.6  christos 
   5666  1.6  christos 	if (no_var)
   5667  1.6  christos 		*no_var = !global_fields[i].param1;
   5668  1.6  christos 	return global_fields[i].name;
   5669  1.6  christos }
   5670  1.6  christos 
   5671  1.6  christos 
   5672  1.9  christos /**
   5673  1.9  christos  * wpa_config_process_global - Set a variable in global configuration
   5674  1.9  christos  * @config: Pointer to global configuration data
   5675  1.9  christos  * @pos: Name and value in the format "{name}={value}"
   5676  1.9  christos  * @line: Line number in configuration file or 0 if not used
   5677  1.9  christos  * Returns: 0 on success with a possible change in value, 1 on success with no
   5678  1.9  christos  * change to previously configured value, or -1 on failure
   5679  1.9  christos  *
   5680  1.9  christos  * This function can be used to set global configuration variables based on
   5681  1.9  christos  * both the configuration file and management interface input. The value
   5682  1.9  christos  * parameter must be in the same format as the text-based configuration file is
   5683  1.9  christos  * using. For example, strings are using double quotation marks.
   5684  1.9  christos  */
   5685  1.2  christos int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
   5686  1.2  christos {
   5687  1.2  christos 	size_t i;
   5688  1.2  christos 	int ret = 0;
   5689  1.2  christos 
   5690  1.2  christos 	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
   5691  1.2  christos 		const struct global_parse_data *field = &global_fields[i];
   5692  1.2  christos 		size_t flen = os_strlen(field->name);
   5693  1.2  christos 		if (os_strncmp(pos, field->name, flen) != 0 ||
   5694  1.2  christos 		    pos[flen] != '=')
   5695  1.2  christos 			continue;
   5696  1.2  christos 
   5697  1.9  christos 		ret = field->parser(field, config, line, pos + flen + 1);
   5698  1.9  christos 		if (ret < 0) {
   5699  1.2  christos 			wpa_printf(MSG_ERROR, "Line %d: failed to "
   5700  1.2  christos 				   "parse '%s'.", line, pos);
   5701  1.2  christos 			ret = -1;
   5702  1.2  christos 		}
   5703  1.9  christos 		if (ret == 1)
   5704  1.9  christos 			break;
   5705  1.2  christos 		if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN)
   5706  1.2  christos 			config->wps_nfc_pw_from_config = 1;
   5707  1.2  christos 		config->changed_parameters |= field->changed_flag;
   5708  1.2  christos 		break;
   5709  1.2  christos 	}
   5710  1.2  christos 	if (i == NUM_GLOBAL_FIELDS) {
   5711  1.2  christos #ifdef CONFIG_AP
   5712  1.9  christos 		if (os_strncmp(pos, "tx_queue_", 9) == 0) {
   5713  1.9  christos 			char *tmp = os_strchr(pos, '=');
   5714  1.9  christos 
   5715  1.9  christos 			if (!tmp) {
   5716  1.9  christos 				if (line < 0)
   5717  1.9  christos 					wpa_printf(MSG_ERROR,
   5718  1.9  christos 						   "Line %d: invalid line %s",
   5719  1.9  christos 						   line, pos);
   5720  1.9  christos 				return -1;
   5721  1.9  christos 			}
   5722  1.9  christos 			*tmp++ = '\0';
   5723  1.9  christos 			if (hostapd_config_tx_queue(config->tx_queue, pos,
   5724  1.9  christos 						    tmp)) {
   5725  1.9  christos 				wpa_printf(MSG_ERROR,
   5726  1.9  christos 					   "Line %d: invalid TX queue item",
   5727  1.9  christos 					   line);
   5728  1.9  christos 				return -1;
   5729  1.9  christos 			}
   5730  1.9  christos 			return ret;
   5731  1.9  christos 		}
   5732  1.9  christos 
   5733  1.2  christos 		if (os_strncmp(pos, "wmm_ac_", 7) == 0) {
   5734  1.2  christos 			char *tmp = os_strchr(pos, '=');
   5735  1.2  christos 			if (tmp == NULL) {
   5736  1.2  christos 				if (line < 0)
   5737  1.2  christos 					return -1;
   5738  1.2  christos 				wpa_printf(MSG_ERROR, "Line %d: invalid line "
   5739  1.2  christos 					   "'%s'", line, pos);
   5740  1.2  christos 				return -1;
   5741  1.2  christos 			}
   5742  1.2  christos 			*tmp++ = '\0';
   5743  1.2  christos 			if (hostapd_config_wmm_ac(config->wmm_ac_params, pos,
   5744  1.2  christos 						  tmp)) {
   5745  1.2  christos 				wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
   5746  1.2  christos 					   "AC item", line);
   5747  1.2  christos 				return -1;
   5748  1.2  christos 			}
   5749  1.9  christos 			return ret;
   5750  1.2  christos 		}
   5751  1.2  christos #endif /* CONFIG_AP */
   5752  1.2  christos 		if (line < 0)
   5753  1.2  christos 			return -1;
   5754  1.2  christos 		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
   5755  1.2  christos 			   line, pos);
   5756  1.2  christos 		ret = -1;
   5757  1.2  christos 	}
   5758  1.2  christos 
   5759  1.2  christos 	return ret;
   5760  1.2  christos }
   5761