eapol/eapol_framework/eapol_common/am/common/eap_file_config.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/am/common/eap_file_config.cpp	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,2229 @@
+/*
+* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  EAP and WLAN authentication protocols.
+*
+*/
+
+
+// This is enumeration of EAPOL source code.
+#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+	#undef EAP_FILE_NUMBER_ENUM
+	#define EAP_FILE_NUMBER_ENUM 14 
+	#undef EAP_FILE_NUMBER_DATE 
+	#define EAP_FILE_NUMBER_DATE 1127594498 
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+
+#include "eap_am_memory.h"
+#include "eap_file_config.h"
+#include "eap_automatic_variable.h"
+
+#if defined(_WIN32) && !defined(__GNUC__)
+	#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
+#endif
+
+
+#if 0
+	const u32_t TRACE_FLAGS_CONFIGURE_DATA = TRACE_FLAGS_DEFAULT;
+#else
+	const u32_t TRACE_FLAGS_CONFIGURE_DATA = eap_am_tools_c::eap_trace_mask_none;
+#endif
+
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+
+eap_config_value_c::~eap_config_value_c()
+{
+	delete m_subsection_map;
+	m_subsection_map = 0;
+}
+
+eap_config_value_c::eap_config_value_c(
+	abs_eap_am_tools_c* const tools)
+	: m_am_tools(tools)
+	, m_subsection_map(0)
+	, m_data(tools)
+	, m_type(eap_configure_type_none)
+	, m_is_valid(false)
+{
+	if (m_data.get_is_valid() == false)
+	{
+		return;
+	}
+
+	m_is_valid = true;
+}
+
+void eap_config_value_c::set_subsection(
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const subsection_map)
+{
+	m_subsection_map = subsection_map;
+}
+
+eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * eap_config_value_c::get_subsection()
+{
+	return m_subsection_map;
+}
+
+eap_variable_data_c * eap_config_value_c::get_data()
+{
+	return &m_data;
+}
+
+void eap_config_value_c::set_type(const eap_configure_type_e type)
+{
+	m_type = type;
+}
+
+eap_configure_type_e eap_config_value_c::get_type()
+{
+	return m_type;
+}
+
+void eap_config_value_c::object_increase_reference_count()
+{
+}
+
+bool eap_config_value_c::get_is_valid()
+{
+	return m_is_valid;
+}
+
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+
+
+EAP_FUNC_EXPORT eap_file_config_c::eap_file_config_c(
+	abs_eap_am_tools_c* const tools)
+: m_am_tools(tools)
+, m_config_map(tools, this)
+, m_is_valid(false)
+{
+	EAP_UNREFERENCED_PARAMETER(TRACE_FLAGS_CONFIGURE_DATA); // in release
+	
+	set_is_valid();
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_file_config_c::~eap_file_config_c()
+{
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::configure(
+	abs_eap_am_file_input_c * const file)
+{
+	eap_status_e status = read_subsections(file, &m_config_map);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::expand_environment_variables(
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map,
+	const eap_variable_data_c * const original_value,
+	eap_variable_data_c * const expanded_value
+	)
+{
+	eap_status_e status = eap_status_process_general_error;
+
+	if (original_value == 0
+		|| expanded_value == 0
+		)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	const u8_t env_char = '$';
+	const u8_t char_left_parenthesis = '(';
+	const u8_t char_right_parenthesis = ')';
+
+	eap_variable_data_c tmp_value_buffer(m_am_tools);
+	if (tmp_value_buffer.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = tmp_value_buffer.set_buffer_length(MAX_LINE_LENGTH);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	bool expanded_value_when_true = false;
+
+	status = expanded_value->set_copy_of_buffer(original_value);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	for (;;)
+	{
+		u8_t * const start_of_value = expanded_value->get_data(expanded_value->get_data_length());
+
+		u8_t * const env_start = static_cast<u8_t *>(m_am_tools->memchr(
+			start_of_value,
+			env_char,
+			expanded_value->get_data_length()));
+
+		if (env_start == 0)
+		{
+			status = eap_status_ok;
+			break;
+		}
+		else
+		{
+			if (static_cast<u32_t>((env_start+2)-start_of_value) < expanded_value->get_data_length()
+				&& env_start[1] == char_left_parenthesis)
+			{
+				u8_t *tmp_end = start_of_value + expanded_value->get_data_length();
+
+				u8_t *env_end = static_cast<u8_t *>(m_am_tools->memchr(
+					env_start,
+					char_right_parenthesis,
+					tmp_end-env_start));
+				if (env_end != 0)
+				{
+					*env_end = '\0';
+
+					u8_t *env_name = env_start+2;
+
+					eap_variable_data_c env_name_buffer(m_am_tools);
+					if (env_name_buffer.get_is_valid() == false)
+					{
+						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+					}
+
+					status = env_name_buffer.set_buffer(
+						env_name,
+						env_end-env_name,
+						false,
+						false);
+					if (status != eap_status_ok)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+
+					eap_variable_data_c env_value_buffer(m_am_tools);
+					if (env_value_buffer.get_is_valid() == false)
+					{
+						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+					}
+
+					eap_status_e env_status = m_am_tools->getenv(
+						&env_name_buffer,
+						&env_value_buffer);
+
+					eap_variable_data_c parsed_value_buffer(m_am_tools);
+					if (parsed_value_buffer.get_is_valid() == false)
+					{
+						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+					}
+
+					status = parsed_value_buffer.set_buffer_length(MAX_LINE_LENGTH);
+					if (status != eap_status_ok)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+					parsed_value_buffer.set_data_length(MAX_LINE_LENGTH);
+
+					eap_variable_data_c configure_option(m_am_tools);
+					if (configure_option.get_is_valid() == false)
+					{
+						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+					}
+
+					if (env_status != eap_status_ok)
+					{
+						// Next check whether a one of the defined configuration
+						// options match to the variable.
+						eap_configure_type_e configuration_data_type = eap_configure_type_none;
+						static const u32_t EAP_MAX_CONFIG_BUFFER_LENGTH = 256;
+						eap_configuration_field_template_c<EAP_MAX_CONFIG_BUFFER_LENGTH> * const tmp_env_name
+							= new eap_configuration_field_template_c<EAP_MAX_CONFIG_BUFFER_LENGTH>;
+
+						eap_automatic_variable_c<eap_configuration_field_template_c<EAP_MAX_CONFIG_BUFFER_LENGTH> >
+							automatic_tmp_env_name(m_am_tools, tmp_env_name);
+
+						if (tmp_env_name == 0)
+						{
+							return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+						}
+
+						eap_status_e status = tmp_env_name->set_fields(
+							m_am_tools,
+							env_name,
+							eap_configure_type_none,
+							false);
+						if (status != eap_status_ok)
+						{
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, status);
+						}
+
+						status = read_configure(
+							config_map,
+							tmp_env_name->get_field(),
+							&configure_option,
+							&configuration_data_type,
+							false);
+
+						if (status == eap_status_ok)
+						{
+							if (configuration_data_type == eap_configure_type_string)
+							{
+								status = configure_option.add_end_null();
+							}
+							else if (configuration_data_type == eap_configure_type_u32_t)
+							{
+								u32_t * const p_value = reinterpret_cast<u32_t *>(
+									configure_option.get_data(
+										configure_option.get_data_length()));
+								if (p_value != 0)
+								{
+									u32_t value = *p_value;
+
+									status = configure_option.set_buffer_length(EAP_MAX_CONFIG_BUFFER_LENGTH);
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+
+									status = configure_option.set_data_length(EAP_MAX_CONFIG_BUFFER_LENGTH);
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+
+									u32_t length = m_am_tools->snprintf(
+											reinterpret_cast<u8_t *>(
+												configure_option.get_data(
+													configure_option.get_data_length())),
+											EAP_MAX_CONFIG_BUFFER_LENGTH,
+											EAPL("%u"),
+											value);
+									status = configure_option.set_data_length(length);
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+
+									status = configure_option.add_end_null();
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+								}
+							}
+							else if (configuration_data_type == eap_configure_type_boolean)
+							{
+								u32_t * const p_value = reinterpret_cast<u32_t *>(
+									configure_option.get_data(
+										configure_option.get_data_length()));
+								if (p_value != 0)
+								{
+									bool value = (*p_value == 0) ? false : true;
+
+									status = configure_option.set_buffer_length(EAP_MAX_CONFIG_BUFFER_LENGTH);
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+
+									status = configure_option.set_data_length(EAP_MAX_CONFIG_BUFFER_LENGTH);
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+
+									if (value == true)
+									{
+										u32_t length = m_am_tools->snprintf(
+												reinterpret_cast<u8_t *>(
+													configure_option.get_data(
+														configure_option.get_data_length())),
+												EAP_MAX_CONFIG_BUFFER_LENGTH,
+												EAPL("true"));
+										status = configure_option.set_data_length(length);
+										if (status != eap_status_ok)
+										{
+											EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+											return EAP_STATUS_RETURN(m_am_tools, status);
+										}
+									}
+									else
+									{
+										u32_t length = m_am_tools->snprintf(
+												reinterpret_cast<u8_t *>(
+													configure_option.get_data(
+														configure_option.get_data_length())),
+												EAP_MAX_CONFIG_BUFFER_LENGTH,
+												EAPL("false"));
+										configure_option.set_data_length(length);
+									}
+
+									status = configure_option.add_end_null();
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+								}
+							}
+							else if (configuration_data_type == eap_configure_type_hex_data)
+							{
+								u8_t * const p_value = reinterpret_cast<u8_t *>(
+									configure_option.get_data(
+										configure_option.get_data_length()));
+
+								u8_t buffer[3];
+								u8_t comma(',');
+
+								eap_variable_data_c tmp(m_am_tools);
+								if (tmp.get_is_valid() == false)
+								{
+									return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+								}
+
+								for (u32_t ind = 0ul; ind < configure_option.get_data_length(); ind++)
+								{
+									u32_t length = m_am_tools->snprintf(
+											buffer,
+											sizeof(buffer),
+											EAPL("%02x"),
+											p_value[ind]);
+
+									status = tmp.add_data(buffer, length);
+									if (status != eap_status_ok)
+									{
+										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+										return EAP_STATUS_RETURN(m_am_tools, status);
+									}
+
+									if ((ind+1) < configure_option.get_data_length())
+									{
+										status = tmp.add_data(&comma, sizeof(comma));
+										if (status != eap_status_ok)
+										{
+											EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+											return EAP_STATUS_RETURN(m_am_tools, status);
+										}
+									}
+								} // for()
+
+								status = configure_option.set_copy_of_buffer(&tmp);
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+
+								status = configure_option.add_end_null();
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+							}
+						}
+
+						if (configure_option.get_is_valid_data() == false
+							|| configure_option.get_data_length() == 0ul)
+						{
+							#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+								printf("WARNING: CONFIG: unknown environment variable %s.\n",
+									   env_name);
+							#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+							EAP_TRACE_DEBUG(
+								m_am_tools,
+								TRACE_FLAGS_DEFAULT,
+								(EAPL("WARNING: CONFIG: unknown environment variable %s.\n"),
+								 env_name));
+
+							// This is empty environment value.
+						}
+					}
+					else
+					{
+						// OK environment variable found.
+						eap_configure_type_e type = eap_configure_type_none;
+
+						status = cnf_parse_value(
+							&env_value_buffer,
+							&env_name_buffer,
+							&type,
+							&configure_option,
+							true
+							);
+						if (status != eap_status_ok)
+						{
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, status);
+						}
+					}
+
+
+					if (configure_option.get_is_valid_data() == true
+						&& configure_option.get_data_length() > 0ul)
+					{
+						tmp_value_buffer.reset();
+
+						u32_t tmp_index = 0ul;
+
+						if (env_start > start_of_value)
+						{
+							u32_t length_of_begin = env_start-start_of_value;
+							if (length_of_begin > 0ul)
+							{
+								status = tmp_value_buffer.set_copy_of_buffer(
+									expanded_value->get_data(length_of_begin),
+									length_of_begin);
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+
+								tmp_index += length_of_begin;
+							}
+						}
+
+						if (configure_option.get_data_length() > 0ul)
+						{
+							status = tmp_value_buffer.add_data(&configure_option);
+							if (status != eap_status_ok)
+							{
+								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+								return EAP_STATUS_RETURN(m_am_tools, status);
+							}
+
+							tmp_index += configure_option.get_data_length();
+						}
+
+						if (tmp_end > (env_end+1))
+						{
+							u32_t length_of_end = tmp_end-(env_end+1);
+							if (length_of_end > 0ul)
+							{
+								status = tmp_value_buffer.add_data(
+									(env_end+1),
+									length_of_end);
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+
+								tmp_index += length_of_end;
+							}
+						}
+
+						if (tmp_value_buffer.get_is_valid_data() == true
+							&& tmp_value_buffer.get_data_length() > 0ul)
+						{
+							status = expanded_value->set_copy_of_buffer(&tmp_value_buffer);
+							if (status != eap_status_ok)
+							{
+								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+								return EAP_STATUS_RETURN(m_am_tools, status);
+							}
+
+							status = expanded_value->add_end_null();
+							if (status != eap_status_ok)
+							{
+								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+								return EAP_STATUS_RETURN(m_am_tools, status);
+							}
+
+							expanded_value_when_true = true;
+						}
+
+					}
+				}
+				else
+				{
+					#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+						printf("ERROR: CONFIG: illegal configure value %s.\n",
+							   expanded_value->get_data(expanded_value->get_data_length()));
+					#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+					EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+									(EAPL("ERROR: CONFIG: illegal configure value %s.\n"),
+									 expanded_value->get_data(expanded_value->get_data_length())));
+					status = eap_status_illegal_configure_field;
+					break;
+				}
+			}
+			else
+			{
+				#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+					printf("ERROR: CONFIG: illegal configure value %s.\n",
+						   expanded_value->get_data(expanded_value->get_data_length()));
+				#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+				EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+								(EAPL("ERROR: CONFIG: illegal configure value %s.\n"),
+								 expanded_value->get_data(expanded_value->get_data_length())));
+				status = eap_status_illegal_configure_field;
+				break;
+			}
+		}
+	} // for()
+
+	if (status == eap_status_ok
+		&& expanded_value_when_true == true)
+	{
+		#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+			printf("CONFIG: expanded configuration value [%s] => [%s].\n",
+				value,
+				expanded_value);
+		#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+						(EAPL("CONFIG: expanded configuration value [%s] => [%s].\n"),
+						 original_value->get_data(original_value->get_data_length()),
+						 expanded_value->get_data(expanded_value->get_data_length())));
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT u8_t * eap_file_config_c::read_hex_byte(
+	u8_t * cursor,
+	const u8_t * const end,
+	u8_t * const hex_byte)
+{
+	u8_t * start = cursor;
+	bool stop = false;
+
+	while(stop == false && cursor < end)
+	{
+		switch(*cursor)
+		{
+		case static_cast<u8_t>(','):
+		case static_cast<u8_t>(' '):
+		case static_cast<u8_t>('\t'):
+			stop = true;
+			break;
+		default:
+			++cursor;
+			break;
+		}
+
+	}
+
+	if (cursor <= end)
+	{
+		u32_t target_length = sizeof(*hex_byte);
+
+		eap_status_e status = m_am_tools->convert_hex_ascii_to_bytes(
+			start,
+			cursor-start,
+			hex_byte,
+			&target_length);
+		if (status != eap_status_ok)
+		{
+			return 0;
+		}
+
+		return ++cursor;
+	}
+
+	return 0;
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT u8_t * eap_file_config_c::read_u32_t(
+	u8_t * cursor,
+	const u8_t * const end,
+	u32_t * const integer)
+{
+	u8_t * start = cursor;
+	bool stop = false;
+
+	while(stop == false && cursor < end)
+	{
+		switch(*cursor)
+		{
+		case static_cast<u8_t>(','):
+		case static_cast<u8_t>(' '):
+		case static_cast<u8_t>('\t'):
+			stop = true;
+			break;
+		default:
+			++cursor;
+			break;
+		}
+
+	}
+
+	if (cursor <= end)
+	{
+		eap_variable_data_c buffer(m_am_tools);
+		if (buffer.get_is_valid() == false)
+		{
+			(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+			return 0;
+		}
+
+		eap_status_e status = buffer.add_data(start, cursor-start);
+		if (status != eap_status_ok)
+		{
+			(void) EAP_STATUS_RETURN(m_am_tools, status);
+			return 0;
+		}
+
+		status = m_am_tools->number_string_to_u32(
+			buffer.get_data(buffer.get_data_length()),
+			buffer.get_data_length(),
+			integer);
+		if (status != eap_status_ok)
+		{
+			(void) EAP_STATUS_RETURN(m_am_tools, status);
+			return 0;
+		}
+
+		return ++cursor;
+	}
+
+	(void) EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
+	return 0;
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::convert_value(
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map,
+	const eap_variable_data_c * const value_buffer,
+	const eap_configure_type_e type,
+	eap_variable_data_c * const value_data)
+{
+	eap_status_e status = eap_status_process_general_error;
+
+		eap_variable_data_c expanded_value_buffer(m_am_tools);
+		if (expanded_value_buffer.get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = expanded_value_buffer.set_buffer_length(MAX_LINE_LENGTH);
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		expanded_value_buffer.set_data_length(MAX_LINE_LENGTH);
+
+		status = expand_environment_variables(
+			config_map,
+			value_buffer,
+			&expanded_value_buffer);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		
+		if (type == eap_configure_type_u32_t)
+		{
+			u32_t uint_value = 0UL;
+			
+			status = m_am_tools->number_string_to_u32(
+				expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()),
+				expanded_value_buffer.get_data_length(),
+				&uint_value);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			
+			status = value_data->set_copy_of_buffer(
+				&uint_value,
+				sizeof(uint_value));
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+		else if (type == eap_configure_type_boolean)
+		{
+			u32_t uint_value = static_cast<u32_t>(~0);
+			
+			if (!m_am_tools->memcmp(
+					expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()),
+					EAP_FILECONFIG_TRUE,
+					expanded_value_buffer.get_data_length()))
+			{
+				// OK, true
+				uint_value = 1u;
+			}
+			else if (!m_am_tools->memcmp(
+						 expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()),
+						 EAP_FILECONFIG_FALSE,
+						 expanded_value_buffer.get_data_length()))
+			{
+				// OK, false
+				uint_value = 0u;
+			}
+			else
+			{
+#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+				printf("ERROR: CONFIG: illegal boolean value %s\n",
+					   expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()));
+#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+				
+				EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+								(EAPL("ERROR: CONFIG: illegal boolean value %s\n"),
+								 expanded_value_buffer.get_data(expanded_value_buffer.get_data_length())));
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
+			}
+			
+			status = value_data->set_copy_of_buffer(
+				&uint_value,
+				sizeof(uint_value));
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+		else if (type == eap_configure_type_string)
+		{
+			status = value_data->set_copy_of_buffer(
+				&expanded_value_buffer);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+		else if (type == eap_configure_type_hex_data)
+		{
+			status = remove_spaces(&expanded_value_buffer);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			
+			u8_t * cursor = expanded_value_buffer.get_data(expanded_value_buffer.get_data_length());
+			const u8_t * const cursor_end = cursor + expanded_value_buffer.get_data_length();
+			
+			while(cursor < cursor_end)
+			{
+				u8_t hex_byte = 0;
+				cursor = read_hex_byte(
+					cursor,
+					cursor_end,
+					&hex_byte);
+				if (cursor == 0)
+				{
+					break;
+				}
+
+				status = value_data->add_data(&hex_byte, sizeof(hex_byte));
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+			}
+		}
+		else if (type == eap_configure_type_u32array)
+		{
+			status = remove_spaces(&expanded_value_buffer);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			
+			u8_t * cursor = expanded_value_buffer.get_data(expanded_value_buffer.get_data_length());
+			const u8_t * const cursor_end = cursor + expanded_value_buffer.get_data_length();
+			
+			while(cursor < cursor_end)
+			{
+				u32_t integer = 0;
+				cursor = read_u32_t(
+					cursor,
+					cursor_end,
+					&integer);
+				if (cursor == 0)
+				{
+					break;
+				}
+
+				status = value_data->add_data(&integer, sizeof(integer));
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+			}
+		}
+		else
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+		}
+
+		return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::store_configure(
+	abs_eap_am_file_input_c * const file,
+	const eap_variable_data_c * const line,
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map)
+{
+	eap_status_e status = eap_status_process_general_error;
+	
+	eap_variable_data_c name_buffer(m_am_tools);
+	if (name_buffer.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_variable_data_c value_buffer(m_am_tools);
+	if (value_buffer.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_variable_data_c value_data(m_am_tools);
+	if (value_data.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+
+	status = name_buffer.set_buffer_length(MAX_LINE_LENGTH);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	name_buffer.set_data_length(0ul);
+
+	status = value_buffer.set_buffer_length(MAX_LINE_LENGTH);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	value_buffer.set_data_length(0ul);
+
+	eap_configure_type_e type = eap_configure_type_none;
+
+	if (line->compare(
+			EAP_FILECONFIG_SECTION_END,
+			EAP_FILECONFIG_SECTION_END_LENGTH) == 0)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CONFIG: section ends.\n")));
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_section_ends);
+	}
+
+	status = cnf_get_string(
+		line,
+		&name_buffer,
+		&value_buffer,
+		&type);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	if (name_buffer.compare_length(
+			EAP_FILECONFIG_SECTION,
+			EAP_FILECONFIG_SECTION_LENGTH,
+			EAP_FILECONFIG_SECTION_LENGTH) == 0)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CONFIG: section %s.\n"),
+			 name_buffer.get_data(name_buffer.get_data_length())));
+
+		status = name_buffer.set_start_offset(EAP_FILECONFIG_SECTION_LENGTH);
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_core_map_c<eap_config_value_c,
+			abs_eap_core_map_c,
+			eap_variable_data_c> * const section_map
+			= new eap_core_map_c<
+			eap_config_value_c,
+			abs_eap_core_map_c,
+			eap_variable_data_c>(m_am_tools, this);
+
+		eap_automatic_variable_c<eap_core_map_c<
+			eap_config_value_c,
+			abs_eap_core_map_c,
+			eap_variable_data_c> >
+			automatic_section_map(m_am_tools, section_map);
+
+		if (section_map == 0
+			|| section_map->get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = read_section(file, section_map);
+		if (status == eap_status_section_ends)
+		{
+			// Add subsection.
+			eap_config_value_c * config = new eap_config_value_c(m_am_tools);
+
+			eap_automatic_variable_c<eap_config_value_c>
+				automatic_config(m_am_tools, config);
+
+			if (config == 0
+				|| config->get_is_valid() == false)
+			{
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+			}
+			
+			config->set_type(eap_configure_type_subsection);
+
+			config->set_subsection(section_map);
+			automatic_section_map.do_not_free_variable();
+			
+			status = convert_value(
+				&m_config_map, // Note here we use the global name space.
+				&value_buffer,
+				type,
+				&value_data);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			{
+				// selector of the section is <name_buffer>:<value_data>.
+				// section:example=string:match => example:match
+				status = name_buffer.add_data(
+					EAP_FILECONFIG_SECTION_SEPARATOR,
+					EAP_FILECONFIG_SECTION_SEPARATOR_LENGTH);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				status = name_buffer.add_data(&value_data);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				status = name_buffer.add_end_null();
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+			}
+
+			eap_variable_data_c selector(m_am_tools);
+			if (selector.get_is_valid() == false)
+			{
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+			}
+
+			status = selector.set_copy_of_buffer(
+				name_buffer.get_data(),
+				name_buffer.get_data_length());
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			status = config_map->add_handler(&selector, config);
+			if (status == eap_status_ok)
+			{
+				automatic_config.do_not_free_variable();
+			}
+			else if (status == eap_status_handler_exists_error)
+			{
+				// This is dublicate subsection.
+				// We will skip this.
+				EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+								(EAPL("ERROR: CONFIG: section %s is already defined.\n"),
+								 name_buffer.get_data(name_buffer.get_data_length())));
+
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+			}
+			else if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools, 
+				TRACE_FLAGS_DEFAULT, 
+				(EAPL("CONFIG: subsection name"), 
+				 name_buffer.get_data(), 
+				 name_buffer.get_data_length()));
+
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		else
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+	else
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_CONFIGURE_DATA,
+			(EAPL("CONFIG: check subsection %s.\n"),
+			 name_buffer.get_data(name_buffer.get_data_length())));
+
+		eap_configuration_field_template_c<MAX_LINE_LENGTH> * const tmp_name
+			= new eap_configuration_field_template_c<MAX_LINE_LENGTH>;
+	
+		eap_automatic_variable_c<eap_configuration_field_template_c<MAX_LINE_LENGTH> >
+			automatic_tmp_name(m_am_tools, tmp_name);
+	
+		if (tmp_name == 0
+			|| tmp_name->get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = tmp_name->set_fields(
+			m_am_tools,
+			name_buffer.get_data(name_buffer.get_data_length()),
+			type,
+			false);
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_variable_data_c check(m_am_tools);
+		if (check.get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = read_configure(
+			config_map,
+			tmp_name->get_field(),
+			&check,
+			&type,
+			true);
+		if (status == eap_status_ok)
+		{
+			status = name_buffer.add_end_null();
+			if (status != eap_status_ok)
+			{
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			// This subsection is already defined.
+#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+			printf("WARNING: CONFIG: subsection %s is already defined.\n",
+				   name_buffer.get_data(name_buffer.get_data_length()));
+#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+			
+			EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+							(EAPL("WARNING: CONFIG: subsection %s is already defined.\n"),
+							 name_buffer.get_data(name_buffer.get_data_length())));
+
+			// We will skip the dublicate section.
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+		}
+
+		//-------------------------------------------------------------------------------
+
+		eap_config_value_c * config = new eap_config_value_c(m_am_tools);
+
+		eap_automatic_variable_c<eap_config_value_c>
+			automatic_config(m_am_tools, config);
+
+		if (config == 0
+			|| config->get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		config->set_type(type);
+
+		status = convert_value(
+			&m_config_map, // Note here we use the global name space.
+			&value_buffer,
+			type,
+			&value_data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = config->get_data()->set_copy_of_buffer(
+			&value_data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_variable_data_c selector(m_am_tools);
+		if (selector.get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = selector.set_copy_of_buffer(
+			tmp_name->get_field()->get_field(),
+			tmp_name->get_field()->get_field_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		
+		status = config_map->add_handler(&selector, config);
+		if (status == eap_status_ok)
+		{
+			automatic_config.do_not_free_variable();
+		}
+		else //if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CONFIG: option added"),
+			 tmp_name->get_field()->get_field(),
+			 tmp_name->get_field()->get_field_length()));
+		
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("CONFIG: data"), 
+			 config->get_data()->get_data(), 
+			 config->get_data()->get_data_length()));
+
+		//-----------------------------------------------------------------------------
+
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+eap_status_e eap_file_config_c::find_rvalue(
+	const eap_variable_data_c * const config_param,
+	bool * const read_env_value,
+	eap_variable_data_c * const param_name,
+	eap_variable_data_c * const param_value
+	)
+{
+	const u8_t * rvalue = 0;
+	const u8_t *env_value = 0;
+
+	if (config_param == 0
+		|| read_env_value == 0
+		|| param_name == 0
+		|| param_value == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	const u8_t * const param = config_param->get_data(config_param->get_data_length());
+	if (param == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	const u8_t * const param_end
+		= config_param->get_data(config_param->get_data_length())
+		+ config_param->get_data_length();
+	if (param_end == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	for (rvalue = param; *rvalue; rvalue++)
+	{
+		if (*rvalue == '=')
+		{
+			break;
+		}
+	}
+	
+	if (*rvalue == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	// Check are there defined environment variable to override the file configuration.
+	{
+		// backup spaces.
+		const u8_t *tmp_param_end = rvalue;
+
+		for (tmp_param_end--
+				 ; m_am_tools->isspace(*tmp_param_end)
+				 || *tmp_param_end == '\r'
+				 || *tmp_param_end == '\n'
+				 || *tmp_param_end == '='
+				 ; tmp_param_end--)
+		{
+			/* empty */
+		}
+
+		tmp_param_end++;
+		u32_t length = tmp_param_end - param;
+
+
+		eap_status_e status = param_name->add_data(param, length);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		status = param_name->add_end_null();
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_variable_data_c env_value_buffer(m_am_tools);
+		if (env_value_buffer.get_is_valid() == false)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		eap_status_e env_status = m_am_tools->getenv(
+			param_name,
+			&env_value_buffer);
+		if (env_status == eap_status_ok)
+		{
+			env_value = env_value_buffer.get_data(env_value_buffer.get_data_length());
+		}
+		else
+		{
+			env_value = 0;
+		}
+
+		if (env_value != 0)
+		{
+			rvalue = env_value;
+			length = m_am_tools->strlen(reinterpret_cast<const char *>(rvalue));
+			*read_env_value = true;
+		}
+		else
+		{
+			rvalue = tmp_param_end;
+
+			for (; *rvalue; rvalue++)
+			{
+				if (*rvalue == '=')
+				{
+					break;
+				}
+			}
+			
+			for (rvalue++; m_am_tools->isspace(*rvalue) || *rvalue == '\r' || *rvalue == '\n'; rvalue++){
+				/* empty */
+			}
+
+			if (*rvalue == 0)
+			{
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+			}
+
+			length = param_end - rvalue;
+		}
+
+		// There is overriding environment variable.
+		status = param_value->set_copy_of_buffer(rvalue, length);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		status = param_value->add_end_null();
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::cnf_parse_value(
+	const eap_variable_data_c * const found_type_value,
+	const eap_variable_data_c * const found_type_name,
+	eap_configure_type_e * const parsed_type,
+	eap_variable_data_c * const parsed_type_value,
+	const bool is_environment_variable)
+{
+	if (found_type_value == 0
+		|| found_type_name == 0
+		|| parsed_type == 0
+		|| parsed_type_value == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	*parsed_type = eap_configure_type_none;
+
+	u32_t ind;
+	for (ind = 0u; ind < sizeof(eap_configure_type_id)/sizeof(eap_configure_type_id[0]); ind++)
+	{
+		if (!m_am_tools->memcmp(
+				eap_configure_type_id[ind].id,
+				found_type_value->get_data(found_type_value->get_data_length()),
+				eap_configure_type_id[ind].id_length))
+		{
+			*parsed_type = eap_configure_type_id[ind].type;
+			break;
+		}
+	}
+
+	u32_t value_length = found_type_value->get_data_length();
+
+	eap_variable_data_c tmp_buffer(m_am_tools);
+	if (tmp_buffer.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status = tmp_buffer.set_buffer_length(MAX_LINE_LENGTH);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	tmp_buffer.set_data_length(MAX_LINE_LENGTH);
+
+	u8_t * const tmp_value_buffer = tmp_buffer.get_buffer(MAX_LINE_LENGTH);
+	if (tmp_value_buffer == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	const u8_t * used_type_value = found_type_value->get_data(found_type_value->get_data_length());
+	if (used_type_value == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	if (*parsed_type == eap_configure_type_none)
+	{
+		// No type defined.
+		if (is_environment_variable == true)
+		{
+			// Environment variable without type is handled as a string type.
+			*parsed_type = eap_configure_type_string;
+			ind = *parsed_type;
+			m_am_tools->memmove(
+				tmp_value_buffer,
+				eap_configure_type_id[ind].id,
+				eap_configure_type_id[ind].id_length);
+			m_am_tools->memmove(
+				tmp_value_buffer+eap_configure_type_id[ind].id_length,
+				found_type_value->get_data(found_type_value->get_data_length()),
+				value_length);
+			value_length = eap_configure_type_id[ind].id_length+value_length;
+			tmp_value_buffer[value_length] = 0;
+			used_type_value = tmp_value_buffer;
+		}
+		else
+		{
+			#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+				printf("ERROR: CONFIG: no subsection type: %s=%s\n",
+					found_type_name->get_data(found_type_name->get_data_length()),
+					found_type_value->get_data(found_type_value->get_data_length()));
+			#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+			EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+							(EAPL("ERROR: CONFIG: no subsection type: %s=%s\n"),
+							found_type_name->get_data(found_type_name->get_data_length()),
+							found_type_value->get_data(found_type_value->get_data_length())));
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
+		}
+	}
+
+
+	const u8_t * value_end = used_type_value+value_length;
+
+	// Remove separator and spaces.
+	for (value_end--
+			 ; used_type_value < value_end
+			 && (m_am_tools->isspace(*value_end)
+				 || *value_end == '='
+				 || *value_end == '\r'
+				 || *value_end == '\n')
+			 ; value_end--)
+	{
+		/* empty */
+		--value_length;
+	}
+	++value_end;
+
+	const u32_t tmp_length = value_end - used_type_value;
+
+	u32_t len = tmp_length - eap_configure_type_id[ind].id_length;
+
+	status = parsed_type_value->add_data(
+		used_type_value+eap_configure_type_id[ind].id_length,
+		len);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = parsed_type_value->add_end_null();
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	
+	if (is_environment_variable == true)
+	{
+		#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+			printf("CONFIG: %s=%s%s; from environment variable\n",
+				   found_type_name->get_data(found_type_name->get_data_length()),
+				   eap_configure_type_id[ind].id,
+				   parsed_type_value->get_data(parsed_type_value->get_data_length()));
+		#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+						(EAPL("CONFIG: %s=%s%s; from environment variable\n"),
+						 found_type_name->get_data(found_type_name->get_data_length()),
+						 eap_configure_type_id[ind].id,
+						 parsed_type_value->get_data(parsed_type_value->get_data_length())));
+	}
+	else
+	{
+		#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+			printf("CONFIG: %s=%s%s\n",
+				   found_type_name->get_data(found_type_name->get_data_length()),
+				   eap_configure_type_id[ind].id,
+				   parsed_type_value->get_data(parsed_type_value->get_data_length()));
+		#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+						(EAPL("CONFIG: %s=%s%s\n"),
+						 found_type_name->get_data(found_type_name->get_data_length()),
+						 eap_configure_type_id[ind].id,
+						 parsed_type_value->get_data(parsed_type_value->get_data_length())));
+	}
+	
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::cnf_get_string(
+	const eap_variable_data_c * const param,
+	eap_variable_data_c * const param_name,
+	eap_variable_data_c * const param_value,
+	eap_configure_type_e * const type)
+{
+	if (param == 0
+		|| param_name == 0
+		|| param_value == 0
+		|| type == 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	bool env_value = false;
+
+	*type = eap_configure_type_none;
+
+	// Returned value could be pointer to environment value.
+	// Do not modify returned value.
+	eap_status_e status = find_rvalue(
+		param,
+		&env_value,
+		param_name,
+		param_value
+		);
+	
+	if (status != eap_status_ok)
+	{
+		#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+			printf("ERROR: CONFIG: illegal subsection: %s\n",
+				   param->get_data(param->get_data_length()));
+		#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS)
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: CONFIG: illegal subsection: %s\n"),
+			 param->get_data(param->get_data_length())));
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
+	}
+
+	eap_variable_data_c parsed_value(m_am_tools);
+	if (parsed_value.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = cnf_parse_value(
+		param_value,
+		param_name,
+		type,
+		&parsed_value,
+		env_value);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = param_value->set_copy_of_buffer(&parsed_value);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = param_value->add_end_null();
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_subsections(
+	abs_eap_am_file_input_c * const file,
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map)
+{
+	eap_variable_data_c line(m_am_tools);
+	if (line.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status = eap_status_ok;
+
+	// This sets the pre-allocated buffer.
+	status = line.set_buffer_length(MAX_LINE_LENGTH);
+
+	for (;status == eap_status_ok;)
+	{
+		status = get_subsect(file, &line);
+		if (status == eap_status_end_of_file)
+		{
+			// End of file reached.
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+		}
+		else if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = store_configure(file, &line, config_map);
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_section(
+	abs_eap_am_file_input_c * const file,
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map)
+{
+	eap_variable_data_c line(m_am_tools);
+	if (line.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status = eap_status_ok;
+
+	// This sets the pre-allocated buffer.
+	status = line.set_buffer_length(MAX_LINE_LENGTH);
+
+	while (status == eap_status_ok)
+	{
+		status = get_subsect(file, &line);
+		if (status == eap_status_end_of_file)
+		{
+			// End of file reached.
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+		}
+		else if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		if (line.compare(
+				EAP_FILECONFIG_SECTION_START,
+				EAP_FILECONFIG_SECTION_START_LENGTH) == 0)
+		{
+			// Starts new section block.
+			status = read_subsections(
+				file,
+				config_map);
+
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		else
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("ERROR: CONFIG: section start '{' is missing.\n")));
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
+		}
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::remove_spaces(eap_variable_data_c * const buffer)
+{
+	eap_variable_data_c tmp(m_am_tools);
+	if (tmp.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status(eap_status_ok);
+
+	for (u32_t ind = 0ul; ind < buffer->get_data_length(); ind++)
+	{
+		u8_t * const character = buffer->get_data_offset(ind, sizeof(u8_t));
+		if (character == 0)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		if (m_am_tools->isspace(*character) == false)
+		{
+			status = tmp.add_data(character, sizeof(*character));
+			if (status != eap_status_ok)
+			{
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+	} // for()
+
+	status = buffer->set_copy_of_buffer(&tmp);
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::remove_leading_spaces(
+	eap_variable_data_c * const line)
+{
+	if (line->get_data_length() == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+
+	u8_t * const begin = line->get_data(line->get_data_length());
+	if(begin == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+	}
+
+	for (u32_t ind = 0; ind < line->get_data_length(); ind++)
+	{
+		if (begin[ind] != ' '
+			&& begin[ind] != '\t')
+		{
+			eap_status_e status = line->set_start_offset(ind);
+			if (status != eap_status_ok)
+			{
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+		}
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::file_read_line(
+	abs_eap_am_file_input_c * const file,
+	eap_variable_data_c * const line)
+{
+	eap_status_e status(eap_status_ok);
+	bool line_continues(true);
+
+	eap_variable_data_c tmp_line(m_am_tools);
+	if (tmp_line.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	const u32_t TMP_LINE_BUFFER_INITIAL_LENGTH = 256ul;
+
+	status = tmp_line.set_buffer_length(TMP_LINE_BUFFER_INITIAL_LENGTH);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	// This is small optimization that does not free the old buffer.
+	status = line->reset_start_offset_and_data_length();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	do
+	{
+		status = tmp_line.reset_start_offset_and_data_length();
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = file->file_read_line(&tmp_line);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_CONFIGURE_DATA,
+			(EAPL("Configure line"), 
+			 tmp_line.get_data(), 
+			 tmp_line.get_data_length()));
+
+		status = remove_leading_spaces(&tmp_line);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_CONFIGURE_DATA,
+			(EAPL("No spaces line"), 
+			 tmp_line.get_data(), 
+			 tmp_line.get_data_length()));
+
+		if (tmp_line.get_data_length() > 0ul)
+		{
+			u8_t * last_char = tmp_line.get_buffer_offset(
+				tmp_line.get_data_length() - 1ul,
+				sizeof(u8_t));
+
+			if (last_char  != 0
+				&& *last_char == '\\')
+			{
+				// If the last character in the line is '\' then the line continues to the next line.
+				tmp_line.set_data_length(tmp_line.get_data_length() - 1ul);
+			}
+			else
+			{
+				line_continues = false;
+			}
+		}
+		else
+		{
+			line_continues = false;
+		}
+
+		status = line->add_data(&tmp_line);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+	} while(line_continues == true);
+
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_CONFIGURE_DATA,
+		(EAPL("Configure line"), 
+		 tmp_line.get_data(), 
+		 tmp_line.get_data_length()));
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::get_subsect(
+	abs_eap_am_file_input_c * const file,
+	eap_variable_data_c * const line)
+{
+	if( file == 0
+		|| line == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_status_e status(eap_status_ok);
+	
+	for(;status == eap_status_ok;)
+	{
+		status = file_read_line(file, line);
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_CONFIGURE_DATA,
+			(EAPL("Configure line"), 
+			 line->get_data(line->get_data_length()), 
+			 line->get_data_length()));
+
+		// error or end of file
+		if(status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = remove_leading_spaces(line);
+		if(status != eap_status_ok)
+		{
+			// Skip this error.
+			status = eap_status_ok;
+			continue;
+		}
+
+		// too short line, ignore
+		if(line->get_data_length() < 1ul)
+		{
+			continue;
+		}
+
+		u8_t * const result = line->get_data(line->get_data_length());
+		if(result == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+		}
+		
+		// ignore the lines starting with newline, space, tab or '#'
+		if ((*result == '\r')
+			|| (*result == '\n')
+			|| (*result == ' ')
+			|| (*result == '\t')
+			|| (*result == '#'))
+		{
+			continue;
+		}
+		else
+		{
+			// OK we get a line.
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_configure(
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map,
+	const eap_configuration_field_c * const field,
+	eap_variable_data_c* const data,
+	eap_configure_type_e * const configuration_data_type,
+	const bool existence_test)
+{
+	eap_status_e status = eap_status_process_general_error;
+
+	eap_variable_data_c selector(m_am_tools);
+	if (selector.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = selector.set_buffer(
+		field->get_field(),
+		field->get_field_length(),
+		false,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	eap_config_value_c *config = config_map->get_handler(&selector);
+
+	if (config != 0)
+	{
+		status = data->set_copy_of_buffer(config->get_data());
+
+		if (status == eap_status_ok)
+		{
+			*configuration_data_type = config->get_type();
+		}
+		else
+		{
+			*configuration_data_type = eap_configure_type_none;
+		}
+	}
+	else
+	{
+		if (existence_test == false)
+		{
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("WARNING: CONFIG: unknown option"),
+				 field->get_field(),
+				 field->get_field_length()));
+		}
+		status = eap_status_illegal_configure_field;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return status; // Here EAP_STATUS_RETURN() macro is too noisy.
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_configure(
+	const eap_configuration_field_c * const field,
+	eap_variable_data_c* const data,
+	eap_core_map_c<eap_config_value_c, abs_eap_core_map_c, eap_variable_data_c> * const config_map,
+	const bool check_subsection_when_true)
+{
+	eap_status_e status = eap_status_process_general_error;
+
+	eap_variable_data_c selector(m_am_tools);
+	if (selector.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	if (check_subsection_when_true == true
+		&& field->get_subsection() != 0)
+	{
+		status = selector.set_buffer(
+			field->get_subsection());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("CONFIG: finds subsection name"), 
+			 field->get_subsection()->get_data(), 
+			 field->get_subsection()->get_data_length()));
+
+		eap_config_value_c *config = config_map->get_handler(&selector);
+
+		if (config != 0)
+		{
+			if (check_subsection_when_true == true
+				&& config->get_type() == eap_configure_type_subsection)
+			{
+				if (config->get_subsection() != 0)
+				{
+					status = read_configure(
+						field,
+						data,
+						config->get_subsection(),
+						false);
+					if (status == eap_status_ok)
+					{
+						// OK, section configuration found.
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+				}
+				else
+				{
+					EAP_TRACE_DATA_DEBUG(
+						m_am_tools,
+						TRACE_FLAGS_DEFAULT,
+						(EAPL("WARNING: CONFIG: subsection not found"),
+						 field->get_field(),
+						 field->get_field_length()));
+				}
+			}
+		}
+		else
+		{
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("WARNING: CONFIG: subsection not found"),
+				 field->get_field(),
+				 field->get_field_length()));
+		}
+	}
+
+
+
+	{
+		status = selector.set_buffer(
+			field->get_field(),
+			field->get_field_length(),
+			false,
+			false);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_config_value_c *config = config_map->get_handler(&selector);
+
+		if (config != 0)
+		{
+			if (field->get_type() != config->get_type())
+			{
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("WARNING: CONFIG: option type failed: required %d != actual %d\n"),
+					 field->get_type(),
+					 config->get_type()));
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("WARNING: CONFIG: rear option type failed: %s\n"),
+					 field->get_field()));
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_type);
+			}
+
+			status = data->set_copy_of_buffer(config->get_data());
+
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CONFIG: value read from eap_file_config_c: %s\n"),
+				 field->get_field()));
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("value"),
+				 data->get_data(),
+				 data->get_data_length()));
+		}
+		else
+		{
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("WARNING: CONFIG: option not found"),
+				 field->get_field(),
+				 field->get_field_length()));
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
+		}
+
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_configure(
+	const eap_configuration_field_c * const field,
+	eap_variable_data_c* const data)
+{
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_file_config_c::read_configure()"),
+		 field->get_field(),
+		 field->get_field_length()));
+
+	eap_status_e status = read_configure(
+		field,
+		data,
+		&m_config_map,
+		true);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------