18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / Configuration parser and common functions
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/uuid.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_peer/eap.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NO_CONFIG_WRITE
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Structure for network configuration parsing. This data is used to implement
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a generic parser for each network block variable. The table of configuration
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * variables is defined below in this file (ssid_fields[]).
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct parse_data {
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Configuration variable name */
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *name;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Parser function for this variable */
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      int line, const char *value);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Writer function (i.e., to get the variable in text format from
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * internal presentation). */
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Variable specific parameters for the parser. */
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *param1, *param2, *param3, *param4;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* 0 = this variable can be included in debug output and ctrl_iface
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * 1 = this variable contains key/private data and it must not be
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     included in debug output unless explicitly requested. In
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     addition, this variable will not be readable through the
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     ctrl_iface.
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int key_data;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_parse_string(const char *value, size_t *len)
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*value == '"') {
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *pos;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *str;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		value++;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strrchr(value, '"');
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL || pos[1] != '\0')
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = pos - value;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = os_malloc(*len + 1);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (str == NULL)
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(str, value, *len);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str[*len] = '\0';
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return str;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *str;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t tlen, hlen = os_strlen(value);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hlen & 1)
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlen = hlen / 2;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str = os_malloc(tlen + 1);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (str == NULL)
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(value, str, tlen)) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(str);
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		str[tlen] = '\0';
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = tlen;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return (char *) str;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_str(const struct parse_data *data,
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_ssid *ssid,
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				int line, const char *value)
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t res_len, *dst_len;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **dst, *tmp;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(value, "NULL") == 0) {
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data->name);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = NULL;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res_len = 0;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto set;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpa_config_parse_string(value, &res_len);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL) {
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line, data->name,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data->key_data ? "[KEY DATA REMOVED]" : value);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->key_data) {
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      (u8 *) tmp, res_len);
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (u8 *) tmp, res_len);
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param3 && res_len < (size_t) data->param3) {
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "min_len=%ld)", line, data->name,
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) res_len, (long) data->param3);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(tmp);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param4 && res_len > (size_t) data->param4) {
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "max_len=%ld)", line, data->name,
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) res_len, (long) data->param4);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(tmp);
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtset:
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst = (char **) (((u8 *) ssid) + (long) data->param1);
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(*dst);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dst = tmp;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param2)
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst_len = res_len;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int is_hex(const u8 *data, size_t len)
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < len; i++) {
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data[i] < 32 || data[i] >= 127)
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_string_ascii(const u8 *value, size_t len)
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(len + 3);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[0] = '"';
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(buf + 1, value, len);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[len + 1] = '"';
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[len + 2] = '\0';
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_string_hex(const u8 *value, size_t len)
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_zalloc(2 * len + 1);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_string(const u8 *value, size_t len)
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_hex(value, len))
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_config_write_string_hex(value, len);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_config_write_string_ascii(value, len);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_str(const struct parse_data *data,
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_ssid *ssid)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **src;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	src = (char **) (((u8 *) ssid) + (long) data->param1);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*src == NULL)
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param2)
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(*src);
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_string((const u8 *) *src, len);
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
221c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt
222c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#ifdef WPA_UNICODE_SSID
223c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidtstatic char * wpa_config_write_str_unicode(const struct parse_data *data,
224c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt						struct wpa_ssid *ssid)
225c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt{
226c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	size_t len;
227c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	char **src;
228c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt
229c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	src = (char **) (((u8 *) ssid) + (long) data->param1);
230c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	if (*src == NULL)
231c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt		return NULL;
232c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt
233c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	if (data->param2)
234c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
235c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	else
236c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt		len = os_strlen(*src);
237c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt
238c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	return wpa_config_write_string_ascii((const u8 *) *src, len);
239c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt}
240c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#endif
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_int(const struct parse_data *data,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_ssid *ssid,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				int line, const char *value)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *dst;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst = (int *) (((u8 *) ssid) + (long) data->param1);
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dst = atoi(value);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param3 && *dst < (long) data->param3) {
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "min_value=%ld)", line, data->name, *dst,
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (long) data->param3);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst = (long) data->param3;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param4 && *dst > (long) data->param4) {
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "max_value=%ld)", line, data->name, *dst,
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (long) data->param4);
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst = (long) data->param4;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_int(const struct parse_data *data,
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_ssid *ssid)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *src, res;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	src = (int *) (((u8 *) ssid) + (long) data->param1);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = os_malloc(20);
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(value, 20, "%d", *src);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= 20) {
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(value);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value[20 - 1] = '\0';
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return value;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_bssid(const struct parse_data *data,
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct wpa_ssid *ssid, int line,
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *value)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_strcmp(value, "any") == 0) {
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->bssid_set = 0;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_MSGDUMP, "BSSID any");
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hwaddr_aton(value, ssid->bssid)) {
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line, value);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->bssid_set = 1;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_bssid(const struct parse_data *data,
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid)
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ssid->bssid_set)
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = os_malloc(20);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= 20) {
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(value);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value[20 - 1] = '\0';
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return value;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_psk(const struct parse_data *data,
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_ssid *ssid, int line,
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const char *value)
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*value == '"') {
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_PBKDF2
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *pos;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		value++;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strrchr(value, '"');
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = pos - value;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = os_strlen(value);
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 8 || len > 63) {
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %lu (expected: 8..63) '%s'.",
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   line, (unsigned long) len, value);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      (u8 *) value, len);
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(ssid->passphrase, value, len) == 0)
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->psk_set = 0;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ssid->passphrase);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->passphrase = os_malloc(len + 1);
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->passphrase == NULL)
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ssid->passphrase, value, len);
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->passphrase[len] = '\0';
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_PBKDF2 */
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "supported.", line);
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_PBKDF2 */
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    value[PMK_LEN * 2] != '\0') {
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line, value);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->passphrase);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->passphrase = NULL;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->psk_set = 1;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_psk(const struct parse_data *data,
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_ssid *ssid)
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->passphrase)
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_config_write_string_ascii(
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(const u8 *) ssid->passphrase,
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_strlen(ssid->passphrase));
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->psk_set)
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_proto(const struct parse_data *data,
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct wpa_ssid *ssid, int line,
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *value)
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int val = 0, last, errors = 0;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *buf;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_strdup(value);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*start != '\0') {
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*start == ' ' || *start == '\t')
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start++;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*start == '\0')
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end != ' ' && *end != '\t' && *end != '\0')
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = *end == '\0';
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(start, "WPA") == 0)
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_PROTO_WPA;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "RSN") == 0 ||
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 os_strcmp(start, "WPA2") == 0)
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_PROTO_RSN;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   line, start);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last)
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = end + 1;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == 0) {
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Line %d: no proto values configured.", line);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->proto = val;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_proto(const struct parse_data *data,
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid)
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int first = 1, ret;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *pos, *end;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_zalloc(10);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + 10;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->proto & WPA_PROTO_WPA) {
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos)
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		first = 0;
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->proto & WPA_PROTO_RSN) {
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		first = 0;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_key_mgmt(const struct parse_data *data,
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int val = 0, last, errors = 0;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *buf;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_strdup(value);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*start != '\0') {
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*start == ' ' || *start == '\t')
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start++;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*start == '\0')
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end != ' ' && *end != '\t' && *end != '\0')
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = *end == '\0';
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(start, "WPA-PSK") == 0)
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_PSK;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WPA-EAP") == 0)
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_IEEE8021X;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "IEEE8021X") == 0)
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "NONE") == 0)
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_NONE;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WPA-NONE") == 0)
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_WPA_NONE;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "FT-PSK") == 0)
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_FT_PSK;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "FT-EAP") == 0)
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_FT_IEEE8021X;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_PSK_SHA256;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WPS") == 0)
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_KEY_MGMT_WPS;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   line, start);
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last)
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = end + 1;
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == 0) {
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR,
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Line %d: no key_mgmt values configured.", line);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->key_mgmt = val;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_key_mgmt(const struct parse_data *data,
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *pos, *end;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_zalloc(50);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + 50;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sNONE",
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "%sFT-PSK",
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos == buf ? "" : " ");
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "%sFT-EAP",
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos == buf ? "" : " ");
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos == buf ? "" : " ");
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos == buf ? "" : " ");
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "%sWPS",
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos == buf ? "" : " ");
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_cipher(int line, const char *value)
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int val = 0, last;
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *buf;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_strdup(value);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*start != '\0') {
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*start == ' ' || *start == '\t')
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start++;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*start == '\0')
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end != ' ' && *end != '\t' && *end != '\0')
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = *end == '\0';
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(start, "CCMP") == 0)
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_CIPHER_CCMP;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "TKIP") == 0)
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_CIPHER_TKIP;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WEP104") == 0)
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_CIPHER_WEP104;
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "WEP40") == 0)
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_CIPHER_WEP40;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "NONE") == 0)
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_CIPHER_NONE;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   line, start);
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last)
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = end + 1;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == 0) {
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line);
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return val;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_cipher(int cipher)
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *pos, *end;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_zalloc(50);
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + 50;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cipher & WPA_CIPHER_CCMP) {
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sCCMP",
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cipher & WPA_CIPHER_TKIP) {
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sTKIP",
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cipher & WPA_CIPHER_WEP104) {
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sWEP104",
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cipher & WPA_CIPHER_WEP40) {
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sWEP40",
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cipher & WPA_CIPHER_NONE) {
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sNONE",
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_pairwise(const struct parse_data *data,
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int val;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	val = wpa_config_parse_cipher(line, value);
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == -1)
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(0x%x).", line, val);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->pairwise_cipher = val;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_pairwise(const struct parse_data *data,
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_cipher(ssid->pairwise_cipher);
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_group(const struct parse_data *data,
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct wpa_ssid *ssid, int line,
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const char *value)
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int val;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	val = wpa_config_parse_cipher(line, value);
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == -1)
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_CIPHER_WEP40)) {
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(0x%x).", line, val);
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->group_cipher = val;
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_group(const struct parse_data *data,
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid)
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_cipher(ssid->group_cipher);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_auth_alg(const struct parse_data *data,
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int val = 0, last, errors = 0;
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *buf;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_strdup(value);
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*start != '\0') {
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*start == ' ' || *start == '\t')
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start++;
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*start == '\0')
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end != ' ' && *end != '\t' && *end != '\0')
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = *end == '\0';
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(start, "OPEN") == 0)
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_AUTH_ALG_OPEN;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "SHARED") == 0)
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_AUTH_ALG_SHARED;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (os_strcmp(start, "LEAP") == 0)
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val |= WPA_AUTH_ALG_LEAP;
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   line, start);
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last)
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = end + 1;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == 0) {
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR,
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Line %d: no auth_alg values configured.", line);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->auth_alg = val;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_auth_alg(const struct parse_data *data,
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *pos, *end;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_zalloc(30);
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + 30;
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sOPEN",
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sSHARED",
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%sLEAP",
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos == buf ? "" : " ");
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int * wpa_config_parse_freqs(const struct parse_data *data,
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct wpa_ssid *ssid, int line,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const char *value)
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *freqs;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t used, len;
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	used = 0;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 10;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = os_zalloc((len + 1) * sizeof(int));
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freqs == NULL)
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = value;
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos) {
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos == ' ')
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (used == len) {
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int *n;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t i;
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			n = os_realloc(freqs, (len * 2 + 1) * sizeof(int));
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (n == NULL) {
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_free(freqs);
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			for (i = len; i <= len * 2; i++)
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				n[i] = 0;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freqs = n;
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len *= 2;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freqs[used] = atoi(pos);
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs[used] == 0)
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		used++;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(pos + 1, ' ');
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freqs;
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_scan_freq(const struct parse_data *data,
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_ssid *ssid, int line,
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *value)
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *freqs;
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = wpa_config_parse_freqs(data, ssid, line, value);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freqs == NULL)
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->scan_freq);
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->scan_freq = freqs;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_freq_list(const struct parse_data *data,
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_ssid *ssid, int line,
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *value)
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *freqs;
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = wpa_config_parse_freqs(data, ssid, line, value);
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freqs == NULL)
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->freq_list);
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->freq_list = freqs;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_freqs(const struct parse_data *data,
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const int *freqs)
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *pos, *end;
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, ret;
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freqs == NULL)
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = 0;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; freqs[i]; i++)
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_zalloc(10 * count + 1);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + 10 * count + 1;
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; freqs[i]; i++) {
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "%s%u",
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  i == 0 ? "" : " ", freqs[i]);
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= end - pos) {
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end[-1] = '\0';
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return buf;
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_scan_freq(const struct parse_data *data,
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_ssid *ssid)
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_freqs(data, ssid->scan_freq);
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_freq_list(const struct parse_data *data,
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_ssid *ssid)
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_freqs(data, ssid->freq_list);
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_eap(const struct parse_data *data,
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_ssid *ssid, int line,
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const char *value)
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int last, errors = 0;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *buf;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *methods = NULL, *tmp;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t num_methods = 0;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_strdup(value);
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*start != '\0') {
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*start == ' ' || *start == '\t')
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start++;
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*start == '\0')
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end != ' ' && *end != '\t' && *end != '\0')
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = *end == '\0';
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = methods;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		methods = os_realloc(methods,
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     (num_methods + 1) * sizeof(*methods));
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (methods == NULL) {
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(tmp);
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		methods[num_methods].method = eap_peer_get_type(
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start, &methods[num_methods].vendor);
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    methods[num_methods].method == EAP_TYPE_NONE) {
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s'", line, start);
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "You may need to add support for"
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " this EAP method during wpa_supplicant\n"
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "build time configuration.\n"
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "See README for more information.");
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   methods[num_methods].method == EAP_TYPE_LEAP)
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid->leap++;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid->non_leap++;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_methods++;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last)
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = end + 1;
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = methods;
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (methods == NULL) {
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(tmp);
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods[num_methods].vendor = EAP_VENDOR_IETF;
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods[num_methods].method = EAP_TYPE_NONE;
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_methods++;
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "eap methods",
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) methods, num_methods * sizeof(*methods));
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eap.eap_methods = methods;
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_eap(const struct parse_data *data,
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_ssid *ssid)
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, ret;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *pos, *end;
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *name;
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_methods == NULL)
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_zalloc(100);
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + 100;
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name = eap_get_name(eap_methods[i].vendor,
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    eap_methods[i].method);
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (name) {
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = os_snprintf(pos, end - pos, "%s%s",
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  pos == buf ? "" : " ", name);
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ret < 0 || ret >= end - pos)
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += ret;
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end[-1] = '\0';
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_password(const struct parse_data *data,
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *hash;
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(value, "NULL") == 0) {
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ssid->eap.password);
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->eap.password = NULL;
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->eap.password_len = 0;
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(value, "hash:", 5) != 0) {
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *tmp;
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t res_len;
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = wpa_config_parse_string(value, &res_len);
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tmp == NULL) {
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: failed to parse "
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "password.", line);
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      (u8 *) tmp, res_len);
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ssid->eap.password);
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->eap.password = (u8 *) tmp;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->eap.password_len = res_len;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* NtPasswordHash: hash:<32 hex digits> */
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strlen(value + 5) != 2 * 16) {
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(expected 32 hex digits)", line);
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hash = os_malloc(16);
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hash == NULL)
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(value + 5, hash, 16)) {
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(hash);
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->eap.password);
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eap.password = hash;
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eap.password_len = 16;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_password(const struct parse_data *data,
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->eap.password == NULL)
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_config_write_string(
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid->eap.password, ssid->eap.password_len);
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(5 + 32 + 1);
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(buf, "hash:", 5);
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const char *value, int idx)
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, title[20];
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpa_config_parse_string(value, len);
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line, idx, value);
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*len > MAX_WEP_KEY_LEN) {
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line, idx, value);
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(key, buf, *len);
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res >= 0 && (size_t) res < sizeof(title))
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_wep_key0(const struct parse_data *data,
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_parse_wep_key(ssid->wep_key[0],
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&ssid->wep_key_len[0], line,
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					value, 0);
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_wep_key1(const struct parse_data *data,
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_parse_wep_key(ssid->wep_key[1],
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&ssid->wep_key_len[1], line,
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					value, 1);
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_wep_key2(const struct parse_data *data,
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_parse_wep_key(ssid->wep_key[2],
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&ssid->wep_key_len[2], line,
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					value, 2);
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_parse_wep_key3(const struct parse_data *data,
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpa_ssid *ssid, int line,
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *value)
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_parse_wep_key(ssid->wep_key[3],
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&ssid->wep_key_len[3], line,
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					value, 3);
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->wep_key_len[idx] == 0)
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_string(ssid->wep_key[idx],
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ssid->wep_key_len[idx]);
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_wep_key0(const struct parse_data *data,
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_wep_key(ssid, 0);
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_wep_key1(const struct parse_data *data,
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_wep_key(ssid, 1);
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_wep_key2(const struct parse_data *data,
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_wep_key(ssid, 2);
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_write_wep_key3(const struct parse_data *data,
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_write_wep_key(ssid, 3);
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_config_parse_p2p_client_list(const struct parse_data *data,
13711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					    struct wpa_ssid *ssid, int line,
13721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					    const char *value)
13731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
13741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const char *pos;
13751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *buf, *n, addr[ETH_ALEN];
13761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t count;
13771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	buf = NULL;
13791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	count = 0;
13801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = value;
13821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	while (pos && *pos) {
13831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (*pos == ' ')
13841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			pos++;
13851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (hwaddr_aton(pos, addr)) {
13871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: Invalid "
13881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "p2p_client_list address '%s'.",
13891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   line, value);
13901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/* continue anyway */
13911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		} else {
13921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			n = os_realloc(buf, (count + 1) * ETH_ALEN);
13931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (n == NULL) {
13941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				os_free(buf);
13951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return -1;
13961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
13971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			buf = n;
13981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_memcpy(buf + count * ETH_ALEN, addr, ETH_ALEN);
13991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			count++;
14001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "p2p_client_list",
14011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				    addr, ETH_ALEN);
14021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
14031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		pos = os_strchr(pos, ' ');
14051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
14061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(ssid->p2p_client_list);
14081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ssid->p2p_client_list = buf;
14091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ssid->num_p2p_clients = count;
14101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
14121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
14131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef NO_CONFIG_WRITE
14161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic char * wpa_config_write_p2p_client_list(const struct parse_data *data,
14171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       struct wpa_ssid *ssid)
14181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
14191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *value, *end, *pos;
14201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
14211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t i;
14221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0)
14241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
14251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	value = os_malloc(20 * ssid->num_p2p_clients);
14271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (value == NULL)
14281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
14291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = value;
14301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	end = value + 20 * ssid->num_p2p_clients;
14311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; i < ssid->num_p2p_clients; i++) {
14331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = os_snprintf(pos, end - pos, MACSTR " ",
14341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  MAC2STR(ssid->p2p_client_list +
14351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					  i * ETH_ALEN));
14361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (res < 0 || res >= end - pos) {
14371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_free(value);
14381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return NULL;
14391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
14401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		pos += res;
14411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
14421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (pos > value)
14441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		pos[-1] = '\0';
14451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return value;
14471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
14481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* NO_CONFIG_WRITE */
14491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
14511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Helper macros for network block parser */
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OFFSET
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef OFFSET
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OFFSET */
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* OFFSET: Get offset of a variable within the wpa_ssid structure */
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* STR: Define a string variable for an ASCII string; f = field name */
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NO_CONFIG_WRITE
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* NO_CONFIG_WRITE */
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR(f) _STR(f), NULL, NULL, NULL, 0
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STRe(f) _STRe(f), NULL, NULL, NULL, 0
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* STR_LEN: Define a string variable with a separate variable for storing the
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data length. Unlike STR(), this can be used to store arbitrary binary data
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (i.e., even nul termination character). */
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * explicitly specified. */
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NO_CONFIG_WRITE
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* NO_CONFIG_WRITE */
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	OFFSET(f), (void *) 0
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	OFFSET(eap.f), (void *) 0
1496c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#ifdef WPA_UNICODE_SSID
1497c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt/* STR_* variants that do not force conversion to ASCII */
1498c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
1499c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
1500c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
1501c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
1502c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
1503c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
1504c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#endif
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* INT: Define an integer variable */
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT(f) _INT(f), NULL, NULL, 0
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTe(f) _INTe(f), NULL, NULL, 0
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* INT_RANGE: Define an integer variable with allowed value range */
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* FUNC: Define a configuration variable that uses a custom function for
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parsing and writing the value. */
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NO_CONFIG_WRITE
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* NO_CONFIG_WRITE */
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NULL, NULL, NULL, NULL
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FUNC(f) _FUNC(f), 0
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FUNC_KEY(f) _FUNC(f), 1
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Table of network configuration variables. This table is used to parse each
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * network configuration variable, e.g., each line in wpa_supplicant.conf file
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that is inside a network block.
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This table is generated using the helper macros defined above and with
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generous help from the C pre-processor. The field name is stored as a string
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * into .name and for STR and INT types, the offset of the target buffer within
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * offset to the field containing the length of the configuration variable.
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * .param3 and .param4 can be used to mark the allowed range (length for STR
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and value for INT).
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For each configuration line in wpa_supplicant.conf, the parser goes through
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this table and select the entry that matches with the field name. The parser
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function (.parser) is then called to parse the actual value of the field.
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This kind of mechanism makes it easy to add new configuration parameters,
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * since only one line needs to be added into this table and into the
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct wpa_ssid definition if the new variable is either a string or
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * integer. More complex types will need to use their own parser and writer
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * functions.
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct parse_data ssid_fields[] = {
1549c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#ifdef WPA_UNICODE_SSID
1550c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt	{ STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
1551c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#else
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1553c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#endif
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(scan_ssid, 0, 1) },
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(bssid) },
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_KEY(psk) },
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(proto) },
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(key_mgmt) },
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(pairwise) },
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(group) },
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(auth_alg) },
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(scan_freq) },
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(freq_list) },
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(eap) },
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_LENe(identity) },
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_LENe(anonymous_identity) },
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_KEY(password) },
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(ca_cert) },
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(ca_path) },
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(client_cert) },
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(private_key) },
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_KEYe(private_key_passwd) },
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(dh_file) },
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(subject_match) },
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(altsubject_match) },
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(ca_cert2) },
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(ca_path2) },
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(client_cert2) },
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(private_key2) },
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_KEYe(private_key2_passwd) },
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(dh_file2) },
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(subject_match2) },
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(altsubject_match2) },
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(phase1) },
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(phase2) },
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(pcsc) },
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_KEYe(pin) },
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(engine_id) },
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(key_id) },
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(cert_id) },
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(ca_cert_id) },
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_KEYe(pin2) },
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(engine2_id) },
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(key2_id) },
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(cert2_id) },
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(ca_cert2_id) },
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INTe(engine) },
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INTe(engine2) },
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(eapol_flags) },
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_KEY(wep_key0) },
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_KEY(wep_key1) },
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_KEY(wep_key2) },
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_KEY(wep_key3) },
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(wep_tx_keyidx) },
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(priority) },
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(eap_workaround) },
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STRe(pac_file) },
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INTe(fragment_size) },
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(mode, 0, 4) },
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(proactive_key_caching, 0, 1) },
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(disabled, 0, 2) },
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(id_str) },
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(ieee80211w, 0, 2) },
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(peerkey, 0, 1) },
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(mixed_cell, 0, 1) },
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(frequency, 0, 10000) },
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(wpa_ptk_rekey) },
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(bgscan) },
16251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
16261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ FUNC(p2p_client_list) },
16271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */
1628c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_HT_OVERRIDES
1629c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ INT_RANGE(disable_ht, 0, 1) },
1630c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ INT_RANGE(disable_ht40, -1, 1) },
1631c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ INT_RANGE(disable_max_amsdu, -1, 1) },
1632c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ INT_RANGE(ampdu_factor, -1, 3) },
1633c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ INT_RANGE(ampdu_density, -1, 7) },
1634c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ STR(ht_mcs) },
1635c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_HT_OVERRIDES */
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#ifdef WPA_UNICODE_SSID
1639c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#undef _STR_UNICODE
1640c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#undef STR_UNICODE
1641c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#undef _STR_LEN_UNICODE
1642c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#undef STR_LEN_UNICODE
1643c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#undef _STR_RANGE_UNICODE
1644c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#undef STR_RANGE_UNICODE
1645c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt#endif
1646c5da5d2e24c1148757b2493dc351c4adec48360dDmitry Shmidt
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef OFFSET
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _STR
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR_KEY
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _STR_LEN
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR_LEN
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR_LEN_KEY
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _STR_RANGE
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR_RANGE
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR_RANGE_KEY
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _INT
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef INT
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef INT_RANGE
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _FUNC
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef FUNC
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef FUNC_KEY
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_add_prio_network - Add a network to priority lists
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to the network configuration to be added to the list
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to add a network block to the priority list of
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * networks. This must be called for each network when reading in the full
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration. In addition, this can be used indirectly when updating
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * priorities by calling wpa_config_update_prio_list().
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_add_prio_network(struct wpa_config *config,
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_ssid *ssid)
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prio;
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *prev, **nlist;
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Add to an existing priority list if one is available for the
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * configured priority level for this network.
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (prio = 0; prio < config->num_prio; prio++) {
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = config->pssid[prio];
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (prev->priority == ssid->priority) {
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			while (prev->pnext)
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev = prev->pnext;
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			prev->pnext = ssid;
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* First network for this priority - add a new priority list */
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nlist = os_realloc(config->pssid,
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (config->num_prio + 1) * sizeof(struct wpa_ssid *));
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nlist == NULL)
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (prio = 0; prio < config->num_prio; prio++) {
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (nlist[prio]->priority < ssid->priority)
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(&nlist[prio + 1], &nlist[prio],
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (config->num_prio - prio) * sizeof(struct wpa_ssid *));
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nlist[prio] = ssid;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->num_prio++;
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->pssid = nlist;
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_update_prio_list - Update network priority list
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to update the priority list of networks in the
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration when a network is being added or removed. This is also called
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * if a priority for a network is changed.
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_update_prio_list(struct wpa_config *config)
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->pssid);
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->pssid = NULL;
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->num_prio = 0;
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = config->ssid;
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->pnext = NULL;
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_config_add_prio_network(config, ssid) < 0)
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_config_free(struct eap_peer_config *eap)
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->eap_methods);
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->identity);
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->anonymous_identity);
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->password);
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->ca_cert);
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->ca_path);
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->client_cert);
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->private_key);
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->private_key_passwd);
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->dh_file);
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->subject_match);
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->altsubject_match);
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->ca_cert2);
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->ca_path2);
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->client_cert2);
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->private_key2);
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->private_key2_passwd);
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->dh_file2);
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->subject_match2);
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->altsubject_match2);
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->phase1);
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->phase2);
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->pcsc);
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->pin);
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->engine_id);
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->key_id);
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->cert_id);
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->ca_cert_id);
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->key2_id);
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->cert2_id);
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->ca_cert2_id);
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->pin2);
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->engine2_id);
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->otp);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->pending_req_otp);
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->pac_file);
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eap->new_password);
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_free_ssid - Free network/ssid configuration data
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Configuration data for the network
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function frees all resources allocated for the network configuration
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data.
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_free_ssid(struct wpa_ssid *ssid)
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->ssid);
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->passphrase);
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_peer_config_free(&ssid->eap);
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->id_str);
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->scan_freq);
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->freq_list);
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid->bgscan);
18111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(ssid->p2p_client_list);
1812c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_HT_OVERRIDES
1813c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_free(ssid->ht_mcs);
1814c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_HT_OVERRIDES */
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ssid);
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_free - Free configuration data
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function frees all resources allocated for the configuration data by
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_read().
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_free(struct wpa_config *config)
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config_blob *blob, *prevblob;
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid, *prev = NULL;
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = config->ssid;
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = ssid;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_free_ssid(prev);
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blob = config->blobs;
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prevblob = NULL;
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (blob) {
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prevblob = blob;
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		blob = blob->next;
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_free_blob(prevblob);
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->ctrl_interface);
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->ctrl_interface_group);
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->opensc_engine_path);
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->pkcs11_engine_path);
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->pkcs11_module_path);
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->driver_param);
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->device_name);
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->manufacturer);
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->model_name);
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->model_number);
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->serial_number);
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->config_methods);
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->p2p_ssid_postfix);
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->pssid);
18641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(config->home_realm);
18651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(config->home_username);
18661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(config->home_password);
18671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(config->home_ca_cert);
18681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(config->home_imsi);
18691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(config->home_milenage);
1870c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef ANDROID_P2P
1871c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_free(config->prioritize);
1872c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config);
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_foreach_network - Iterate over each configured network
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @func: Callback function to process each network
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @arg: Opaque argument to pass to callback function
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Iterate over the set of configured networks calling the specified
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function for each item. We guard against callbacks removing the
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supplied network.
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_foreach_network(struct wpa_config *config,
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void (*func)(void *, struct wpa_ssid *),
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *arg)
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid, *next;
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = config->ssid;
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = ssid->next;
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		func(arg, ssid);
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = next;
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_get_network - Get configured network based on id
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: Unique network id to search for
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Network configuration or %NULL if not found
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = config->ssid;
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (id == ssid->id)
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssid;
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_add_network - Add a new network with empty configuration
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: The new network configuration or %NULL if operation failed
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int id;
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid, *last = NULL;
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	id = -1;
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = config->ssid;
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->id > id)
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			id = ssid->id;
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = ssid;
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	id++;
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = os_zalloc(sizeof(*ssid));
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->id = id;
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (last)
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last->next = ssid;
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->ssid = ssid;
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_update_prio_list(config);
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssid;
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_remove_network - Remove a configured network based on id
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: Unique network id to search for
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 if the network was not found
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_remove_network(struct wpa_config *config, int id)
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid, *prev = NULL;
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = config->ssid;
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (ssid) {
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (id == ssid->id)
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = ssid;
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = ssid->next;
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev)
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev->next = ssid->next;
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->ssid = ssid->next;
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_update_prio_list(config);
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_free_ssid(ssid);
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_set_network_defaults - Set network default values
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to network configuration data
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_set_network_defaults(struct wpa_ssid *ssid)
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->proto = DEFAULT_PROTO;
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->group_cipher = DEFAULT_GROUP;
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->key_mgmt = DEFAULT_KEY_MGMT;
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
2005c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_HT_OVERRIDES
2006c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	ssid->disable_ht = DEFAULT_DISABLE_HT;
2007c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
2008c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
2009c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
2010c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
2011c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_HT_OVERRIDES */
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_set - Set a variable in network configuration
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to network configuration data
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @var: Variable name, e.g., "ssid"
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @value: Variable value
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @line: Line number in configuration file or 0 if not used
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to set network configuration variables based on
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * both the configuration file and management interface input. The value
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parameter must be in the same format as the text-based configuration file is
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * using. For example, strings are using double quotation marks.
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   int line)
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL || var == NULL || value == NULL)
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_SSID_FIELDS; i++) {
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct parse_data *field = &ssid_fields[i];
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(var, field->name) != 0)
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (field->parser(field, ssid, line, value)) {
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (line) {
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "Line %d: failed to "
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "parse %s '%s'.", line, var, value);
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i == NUM_SSID_FIELDS) {
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (line) {
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s'.", line, var);
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
20641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  const char *value)
20651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
20661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t len;
20671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *buf;
20681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int ret;
20691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	len = os_strlen(value);
20711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	buf = os_malloc(len + 3);
20721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (buf == NULL)
20731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
20741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	buf[0] = '"';
20751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memcpy(buf + 1, value, len);
20761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	buf[len + 1] = '"';
20771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	buf[len + 2] = '\0';
20781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ret = wpa_config_set(ssid, var, buf, 0);
20791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(buf);
20801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return ret;
20811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
20821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_get_all - Get all options from network configuration
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to network configuration data
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @get_keys: Determines if keys/passwords will be included in returned list
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	(if they may be exported)
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: %NULL terminated list of all set keys and their values in the form
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of [key1, val1, key2, val2, ... , NULL]
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to get list of all configured network properties.
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The caller is responsible for freeing the returned list and all its
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * elements.
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct parse_data *field;
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *key, *value;
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **props;
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int fields_num;
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	get_keys = get_keys && ssid->export_keys;
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1));
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!props)
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fields_num = 0;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_SSID_FIELDS; i++) {
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		field = &ssid_fields[i];
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (field->key_data && !get_keys)
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		value = field->writer(field, ssid);
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value == NULL)
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strlen(value) == 0) {
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(value);
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key = os_strdup(field->name);
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key == NULL) {
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(value);
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto err;
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		props[fields_num * 2] = key;
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		props[fields_num * 2 + 1] = value;
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fields_num++;
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return props;
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = *props;
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (value)
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(value++);
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(props);
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_CONFIG_WRITE
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_get - Get a variable in network configuration
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to network configuration data
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @var: Variable name, e.g., "ssid"
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Value of the variable or %NULL on failure
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to get network configuration variables. The
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned value is a copy of the configuration variable in text format, i.e,.
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the same format that the text-based configuration file and wpa_config_set()
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are using for the value. The caller is responsible for freeing the returned
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value.
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * wpa_config_get(struct wpa_ssid *ssid, const char *var)
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL || var == NULL)
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_SSID_FIELDS; i++) {
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct parse_data *field = &ssid_fields[i];
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(var, field->name) == 0)
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return field->writer(field, ssid);
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_get_no_key - Get a variable in network configuration (no keys)
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to network configuration data
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @var: Variable name, e.g., "ssid"
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Value of the variable or %NULL on failure
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to get network configuration variable like
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_get(). The only difference is that this functions does not expose
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * key/password material from the configuration. In case a key/password field
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is requested, the returned value is an empty string or %NULL if the variable
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is not set or "*" if the variable is set (regardless of its value). The
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned value is a copy of the configuration variable in text format, i.e,.
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the same format that the text-based configuration file and wpa_config_set()
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are using for the value. The caller is responsible for freeing the returned
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value.
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL || var == NULL)
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_SSID_FIELDS; i++) {
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct parse_data *field = &ssid_fields[i];
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(var, field->name) == 0) {
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			char *res = field->writer(field, ssid);
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (field->key_data) {
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (res && res[0]) {
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					wpa_printf(MSG_DEBUG, "Do not allow "
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   "key_data field to be "
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   "exposed");
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					os_free(res);
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return os_strdup("*");
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_free(res);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return res;
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_CONFIG_WRITE */
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Pointer to network configuration data
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function must be called to update WPA PSK when either SSID or the
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * passphrase has changed for the network configuration.
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_update_psk(struct wpa_ssid *ssid)
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_PBKDF2
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pbkdf2_sha1(ssid->passphrase,
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (char *) ssid->ssid, ssid->ssid_len, 4096,
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ssid->psk, PMK_LEN);
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid->psk, PMK_LEN);
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->psk_set = 1;
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_PBKDF2 */
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_get_blob - Get a named configuration blob
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Name of the blob
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to blob data or %NULL if not found
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   const char *name)
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config_blob *blob = config->blobs;
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (blob) {
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(blob->name, name) == 0)
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return blob;
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		blob = blob->next;
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_set_blob - Set or add a named configuration blob
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @blob: New value for the blob
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Adds a new configuration blob or replaces the current value of an existing
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * blob.
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_set_blob(struct wpa_config *config,
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct wpa_config_blob *blob)
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_remove_blob(config, blob->name);
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blob->next = config->blobs;
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->blobs = blob;
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_free_blob - Free blob data
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @blob: Pointer to blob to be freed
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_free_blob(struct wpa_config_blob *blob)
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (blob) {
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(blob->name);
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(blob->data);
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(blob);
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_remove_blob - Remove a named configuration blob
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Name of the blob to remove
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if blob was removed or -1 if blob was not found
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_remove_blob(struct wpa_config *config, const char *name)
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos) {
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(pos->name, name) == 0) {
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = pos->next;
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				config->blobs = pos->next;
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_config_free_blob(pos);
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = pos;
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos->next;
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_alloc_empty - Allocate an empty configuration
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * socket
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @driver_param: Driver parameters
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated configuration data or %NULL on failure
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const char *driver_param)
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config *config;
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config = os_zalloc(sizeof(*config));
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->eapol_version = DEFAULT_EAPOL_VERSION;
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->ap_scan = DEFAULT_AP_SCAN;
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->fast_reauth = DEFAULT_FAST_REAUTH;
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->max_num_sta = DEFAULT_MAX_NUM_STA;
23481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_interface)
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->ctrl_interface = os_strdup(ctrl_interface);
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (driver_param)
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->driver_param = os_strdup(driver_param);
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config;
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_config_debug_dump_networks - Debug dump of configured networks
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data from wpa_config_read()
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_config_debug_dump_networks(struct wpa_config *config)
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prio;
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (prio = 0; prio < config->num_prio; prio++) {
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = config->pssid[prio];
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Priority group %d",
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ssid->priority);
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ssid) {
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ssid->id,
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid = ssid->pnext;
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct global_parse_data {
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *name;
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int (*parser)(const struct global_parse_data *data,
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct wpa_config *config, int line, const char *value);
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *param1, *param2, *param3;
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int changed_flag;
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_global_config_parse_int(const struct global_parse_data *data,
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_config *config, int line,
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const char *pos)
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *dst;
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst = (int *) (((u8 *) config) + (long) data->param1);
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dst = atoi(pos);
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param2 && *dst < (long) data->param2) {
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "min_value=%ld)", line, data->name, *dst,
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (long) data->param2);
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst = (long) data->param2;
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param3 && *dst > (long) data->param3) {
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "max_value=%ld)", line, data->name, *dst,
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (long) data->param3);
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst = (long) data->param3;
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_global_config_parse_str(const struct global_parse_data *data,
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_config *config, int line,
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const char *pos)
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **dst, *tmp;
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(pos);
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param2 && len < (size_t) data->param2) {
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "min_len=%ld)", line, data->name,
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (long) data->param2);
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->param3 && len > (size_t) data->param3) {
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "max_len=%ld)", line, data->name,
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (long) data->param3);
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = os_strdup(pos);
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst = (char **) (((u8 *) config) + (long) data->param1);
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(*dst);
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dst = tmp;
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_process_country(const struct global_parse_data *data,
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_config *config, int line,
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const char *pos)
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!pos[0] || !pos[1]) {
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Invalid country set");
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->country[0] = pos[0];
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->country[1] = pos[1];
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "country='%c%c'",
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   config->country[0], config->country[1]);
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_process_load_dynamic_eap(
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct global_parse_data *data, struct wpa_config *config,
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int line, const char *so)
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_peer_method_load(so);
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == -2) {
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "reloading.");
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret) {
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "method '%s'.", line, so);
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_process_uuid(const struct global_parse_data *data,
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_config *config, int line,
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *pos)
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[40];
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (uuid_str2bin(pos, config->uuid)) {
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	uuid_bin2str(config->uuid, buf, sizeof(buf));
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_process_device_type(
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct global_parse_data *data,
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config *config, int line, const char *pos)
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wps_dev_type_str2bin(pos, config->device_type);
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_process_os_version(const struct global_parse_data *data,
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_config *config, int line,
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const char *pos)
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(pos, config->os_version, 4)) {
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "os_version=%08x",
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   WPA_GET_BE32(config->os_version));
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_process_sec_device_type(
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct global_parse_data *data,
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config *config, int line, const char *pos)
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int idx;
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "items", line);
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	idx = config->num_sec_device_types;
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->num_sec_device_types++;
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_config_process_hessid(
25581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const struct global_parse_data *data,
25591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_config *config, int line, const char *pos)
25601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
25611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (hwaddr_aton2(pos, config->hessid) < 0) {
25621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
25631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   line, pos);
25641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
25651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
25661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
25671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
25681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
25691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
25701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OFFSET
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef OFFSET
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OFFSET */
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* OFFSET: Get offset of a variable within the wpa_config structure */
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT(f) _INT(f), NULL, NULL
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR(f) _STR(f), NULL, NULL
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct global_parse_data global_fields[] = {
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(ctrl_interface), 0 },
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(ctrl_interface_group), 0 } /* deprecated */,
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(eapol_version, 1, 2), 0 },
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(ap_scan), 0 },
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(fast_reauth), 0 },
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(opensc_engine_path), 0 },
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(pkcs11_engine_path), 0 },
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(pkcs11_module_path), 0 },
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(driver_param), 0 },
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(dot11RSNAConfigPMKLifetime), 0 },
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(dot11RSNAConfigSATimeout), 0 },
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(update_config), 0 },
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC_NO_VAR(load_dynamic_eap), 0 },
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(uuid), CFG_CHANGED_UUID },
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(p2p_listen_reg_class), 0 },
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(p2p_listen_channel), 0 },
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(p2p_oper_reg_class), 0 },
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(p2p_oper_channel), 0 },
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(p2p_go_intent, 0, 15), 0 },
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(p2p_group_idle), 0 },
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
2629c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef ANDROID_P2P
2630c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	{ STR_RANGE(prioritize, 0, 32), CFG_CHANGED_IFACE_PRIORITY },
2631c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ FUNC(country), CFG_CHANGED_COUNTRY },
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(bss_max_count), 0 },
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(bss_expiration_age), 0 },
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(bss_expiration_scan_count), 0 },
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT_RANGE(filter_ssids, 0, 1), 0 },
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ INT(max_num_sta), 0 },
26381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
26391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ STR(home_realm), 0 },
26401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ STR(home_username), 0 },
26411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ STR(home_password), 0 },
26421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ STR(home_ca_cert), 0 },
26431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ STR(home_imsi), 0 },
26441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ STR(home_milenage), 0 },
26451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ INT_RANGE(interworking, 0, 1), 0 },
26461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ FUNC(hessid), 0 },
26471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ INT_RANGE(access_network_type, 0, 15), 0 }
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef FUNC
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _INT
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef INT
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef INT_RANGE
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef _STR
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR_RANGE
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_process_global(struct wpa_config *config, char *pos, int line)
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct global_parse_data *field = &global_fields[i];
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t flen = os_strlen(field->name);
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(pos, field->name, flen) != 0 ||
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos[flen] != '=')
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (field->parser(field, config, line, pos + flen + 1)) {
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: failed to "
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "parse '%s'.", line, pos);
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->changed_parameters |= field->changed_flag;
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i == NUM_GLOBAL_FIELDS) {
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (line < 0)
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   line, pos);
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2690