eapol/eapol_framework/eapol_common/core/eap_core.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
equal deleted inserted replaced
-1:000000000000 0:c8830336c852
       
     1 /*
       
     2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  EAP and WLAN authentication protocols.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // This is enumeration of EAPOL source code.
       
    20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    21 	#undef EAP_FILE_NUMBER_ENUM
       
    22 	#define EAP_FILE_NUMBER_ENUM 44 
       
    23 	#undef EAP_FILE_NUMBER_DATE 
       
    24 	#define EAP_FILE_NUMBER_DATE 1127594498 
       
    25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    26 
       
    27 
       
    28 
       
    29 #include "eap_am_memory.h"
       
    30 #include "eap_tools.h"
       
    31 #include "eap_core.h"
       
    32 #include "eap_core_nak_info.h"
       
    33 #include "eap_state_notification.h"
       
    34 #include "eap_network_id_selector.h"
       
    35 #include "eap_buffer.h"
       
    36 #include "eap_header_string.h"
       
    37 #include "eap_automatic_variable.h"
       
    38 
       
    39 
       
    40 /**
       
    41  * This is the character that separates routing realms.
       
    42  */
       
    43 const u8_t EAP_NAI_ROUTING_REALM_SEPARATOR[] = "!";
       
    44 
       
    45 /**
       
    46  * This is the at character of NAI.
       
    47  */
       
    48 const u8_t EAP_NAI_AT_CHARACTER[] = "@";
       
    49 
       
    50 
       
    51 //--------------------------------------------------
       
    52 
       
    53 // 
       
    54 EAP_FUNC_EXPORT eap_core_c::~eap_core_c()
       
    55 {
       
    56 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    57 
       
    58 	EAP_TRACE_DEBUG(
       
    59 		m_am_tools, 
       
    60 		TRACE_FLAGS_DEFAULT, 
       
    61 		(EAPL("eap_core_c::~eap_core_c(): %s, %s, this = 0x%08x => 0x%08x.\n"),
       
    62 		(m_is_client == true) ? "client": "server",
       
    63 		(m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
    64 		this,
       
    65 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
    66 
       
    67 	EAP_ASSERT(m_shutdown_was_called == true);
       
    68 
       
    69 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    70 }
       
    71 
       
    72 //--------------------------------------------------
       
    73 
       
    74 #if defined(_WIN32) && !defined(__GNUC__)
       
    75 	#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
       
    76 #endif
       
    77 
       
    78 // 
       
    79 EAP_FUNC_EXPORT eap_core_c::eap_core_c(
       
    80 	abs_eap_am_tools_c * const tools,
       
    81 	abs_eap_core_c * const partner,
       
    82 	const bool is_client_when_true,
       
    83 	const eap_am_network_id_c * const receive_network_id,
       
    84 	const bool is_tunneled_eap)
       
    85 	: m_partner(partner)
       
    86 	, m_am_tools(tools)
       
    87 	, m_type_map(tools, this)
       
    88 	, m_current_eap_type(eap_type_none)
       
    89 	, m_default_eap_type(eap_type_none)
       
    90 	, m_eap_identity(tools)
       
    91 	, m_eap_header_offset(0u)
       
    92 	, m_MTU(0u)
       
    93 	, m_trailer_length(0u)
       
    94 	, m_receive_network_id(tools)
       
    95 	, m_retransmission(0)
       
    96 	, m_retransmission_time(EAP_CORE_RETRANSMISSION_TIME)
       
    97 	, m_retransmission_counter(EAP_CORE_RETRANSMISSION_COUNTER)
       
    98 	, m_session_timeout(EAP_CORE_SESSION_TIMEOUT)
       
    99 	, m_eap_core_failure_received_timeout(EAP_CORE_FAILURE_RECEIVED_TIMEOUT)
       
   100 	, m_remove_session_timeout(EAP_CORE_REMOVE_SESSION_TIMEOUT)
       
   101 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
   102 	, m_wait_eap_request_type_timeout(EAP_CORE_WAIT_EAP_REQUEST_TYPE_TIMEOUT)
       
   103 	, m_wait_eap_request_type_timeout_set(false)
       
   104 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
   105 	, m_eap_identity_request_identifier_client(0)
       
   106 	, m_is_client(is_client_when_true)
       
   107 	, m_is_client_role(is_client_when_true)
       
   108 	, m_is_valid(false)
       
   109 	, m_client_restart_authentication_initiated(false)
       
   110 	, m_marked_removed(false)
       
   111 	, m_eap_identity_response_accepted(false)
       
   112 	, m_shutdown_was_called(false)
       
   113 	, m_eap_type_response_sent(false)
       
   114 	, m_is_tunneled_eap(is_tunneled_eap)
       
   115 #if defined(USE_EAP_CORE_SERVER)
       
   116 	, m_process_eap_nak_immediately(EAP_CORE_PROCESS_EAP_NAK_IMMEDIATELY)
       
   117 	, m_nak_process_timer_active(false)
       
   118 	, m_eap_identity_request_send(false)
       
   119 	, m_eap_identity_response_received(false)
       
   120 	, m_eap_failure_sent(false)
       
   121 	, m_send_eap_success_after_notification(false)
       
   122 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
   123 	, m_skip_eap_request_identity(false)
       
   124 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
   125 #endif //#if defined(USE_EAP_CORE_SERVER)
       
   126 	, m_use_eap_expanded_type(false)
       
   127 	, m_ignore_eap_failure(false)
       
   128 	, m_ignore_notifications(false)
       
   129 {
       
   130 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   131 
       
   132 	EAP_TRACE_DEBUG(
       
   133 		m_am_tools, 
       
   134 		TRACE_FLAGS_DEFAULT, 
       
   135 		(EAPL("eap_core_c::eap_core_c(): %s, %s, this = 0x%08x => 0x%08x, compiled %s %s.\n"),
       
   136 		(m_is_client == true) ? "client": "server",
       
   137 		(m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   138 		this,
       
   139 		dynamic_cast<abs_eap_base_timer_c *>(this),
       
   140 		__DATE__,
       
   141 		__TIME__));
       
   142 
       
   143 	eap_status_e status = m_receive_network_id.set_copy_of_network_id(receive_network_id);
       
   144 	if (status != eap_status_ok)
       
   145 	{
       
   146 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   147 		return;
       
   148 	}
       
   149 
       
   150 	set_is_valid();
       
   151 
       
   152 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   153 }
       
   154 
       
   155 //--------------------------------------------------
       
   156 
       
   157 //
       
   158 EAP_FUNC_EXPORT abs_eap_core_c * eap_core_c::get_partner()
       
   159 {
       
   160 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
   161 
       
   162 	return m_partner;
       
   163 }
       
   164 
       
   165 //--------------------------------------------------
       
   166 
       
   167 //
       
   168 EAP_FUNC_EXPORT void eap_core_c::set_partner(abs_eap_core_c * const partner)
       
   169 {
       
   170 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
   171 
       
   172 	m_partner = partner;
       
   173 }
       
   174 
       
   175 //--------------------------------------------------
       
   176 
       
   177 //
       
   178 EAP_FUNC_EXPORT void eap_core_c::set_is_valid()
       
   179 {
       
   180 	m_is_valid = true;
       
   181 }
       
   182 
       
   183 //--------------------------------------------------
       
   184 
       
   185 //
       
   186 EAP_FUNC_EXPORT bool eap_core_c::get_is_valid()
       
   187 {
       
   188 	return m_is_valid;
       
   189 }
       
   190 
       
   191 //--------------------------------------------------
       
   192 
       
   193 //
       
   194 EAP_FUNC_EXPORT void eap_core_c::object_increase_reference_count()
       
   195 {
       
   196 }
       
   197 
       
   198 //--------------------------------------------------
       
   199 
       
   200 //
       
   201 EAP_FUNC_EXPORT u32_t eap_core_c::object_decrease_reference_count()
       
   202 {
       
   203 	return 0u;
       
   204 }
       
   205 
       
   206 //--------------------------------------------------
       
   207 
       
   208 //
       
   209 EAP_FUNC_EXPORT bool eap_core_c::get_marked_removed()
       
   210 {
       
   211 	return m_marked_removed;
       
   212 }
       
   213 
       
   214 //--------------------------------------------------
       
   215 
       
   216 //
       
   217 EAP_FUNC_EXPORT void eap_core_c::set_marked_removed()
       
   218 {
       
   219 	m_marked_removed = true;
       
   220 }
       
   221 
       
   222 //--------------------------------------------------
       
   223 
       
   224 //
       
   225 EAP_FUNC_EXPORT void eap_core_c::unset_marked_removed()
       
   226 {
       
   227 	m_marked_removed = false;
       
   228 }
       
   229 
       
   230 
       
   231 //--------------------------------------------------
       
   232 
       
   233 //
       
   234 EAP_FUNC_EXPORT void eap_core_c::ignore_notifications()
       
   235 {
       
   236 	m_ignore_notifications = true;
       
   237 }
       
   238 
       
   239 //--------------------------------------------------
       
   240 
       
   241 //
       
   242 eap_status_e eap_core_c::initialize_asynchronous_init_remove_eap_session(
       
   243 	const u32_t remove_session_timeout)
       
   244 {
       
   245 	EAP_TRACE_DEBUG(
       
   246 		m_am_tools, 
       
   247 		TRACE_FLAGS_DEFAULT, 
       
   248 		(EAPL("eap_core_c::initialize_asynchronous_init_remove_eap_session(): %s.\n"),
       
   249 		 (m_is_client == true) ? "client": "server"));
       
   250 
       
   251 	eap_status_e status = eap_status_process_general_error;
       
   252 
       
   253 
       
   254 	if (m_is_client_role == false)
       
   255 	{
       
   256 		// Server stops re-transmissions.
       
   257 		// Client can re-transmit until session is removed.
       
   258 		cancel_retransmission();
       
   259 	}
       
   260 
       
   261 	cancel_eap_failure_timeout();
       
   262 
       
   263 	cancel_session_timeout();
       
   264 
       
   265 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
   266 	if (m_is_tunneled_eap == false
       
   267 		&& m_is_client_role == true)
       
   268 	{
       
   269 		cancel_wait_eap_request_type_timeout();
       
   270 	}
       
   271 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
   272 
       
   273 	set_marked_removed();
       
   274 
       
   275 
       
   276 	if (remove_session_timeout == 0ul)
       
   277 	{
       
   278 		status = asynchronous_init_remove_eap_session();
       
   279 	}
       
   280 	else
       
   281 	{
       
   282 		EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   283 
       
   284 		cancel_asynchronous_init_remove_eap_session();
       
   285 
       
   286 		status = m_partner->set_timer(
       
   287 			this,
       
   288 			EAP_CORE_REMOVE_SESSION_TIMEOUT_ID,
       
   289 			0,
       
   290 			remove_session_timeout);
       
   291 
       
   292 		if (status != eap_status_ok)
       
   293 		{
       
   294 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   295 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   296 		}
       
   297 
       
   298 		EAP_TRACE_DEBUG(
       
   299 			m_am_tools, 
       
   300 			TRACE_FLAGS_DEFAULT, 
       
   301 			(EAPL("TIMER: %s: %s, EAP_CORE_REMOVE_SESSION_TIMEOUT_ID set %d ms, this = 0x%08x.\n"),
       
   302 			 (m_is_client == true) ? "client": "server",
       
   303 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   304 			 remove_session_timeout,
       
   305 			 this));
       
   306 	}
       
   307 
       
   308 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   309 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   310 }
       
   311 
       
   312 //--------------------------------------------------
       
   313 
       
   314 eap_status_e eap_core_c::cancel_asynchronous_init_remove_eap_session()
       
   315 {
       
   316 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   317 
       
   318 	if (m_partner != 0)
       
   319 	{
       
   320 		eap_status_e status = m_partner->cancel_timer(
       
   321 			this,
       
   322 			EAP_CORE_REMOVE_SESSION_TIMEOUT_ID);
       
   323 
       
   324 		EAP_UNREFERENCED_PARAMETER(status); // in release
       
   325 		
       
   326 		EAP_TRACE_DEBUG(
       
   327 			m_am_tools, 
       
   328 			TRACE_FLAGS_DEFAULT, 
       
   329 			(EAPL("TIMER: %s: %s, EAP_CORE_REMOVE_SESSION_TIMEOUT_ID cancelled status %d, this = 0x%08x.\n"),
       
   330 			 (m_is_client == true ? "client": "server"),
       
   331 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   332 			 status,
       
   333 			 this));
       
   334 	}
       
   335 
       
   336 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   337 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   338 }
       
   339 
       
   340 //--------------------------------------------------
       
   341 
       
   342 //
       
   343 eap_status_e eap_core_c::asynchronous_init_remove_eap_session()
       
   344 {
       
   345 	EAP_TRACE_DEBUG(
       
   346 		m_am_tools, 
       
   347 		TRACE_FLAGS_DEFAULT, 
       
   348 		(EAPL("eap_core_c::asynchronous_init_remove_eap_session(): %s.\n"),
       
   349 		 (m_is_client == true) ? "client": "server"));
       
   350 
       
   351 		eap_am_network_id_c send_network_id(
       
   352 			m_am_tools,
       
   353 			m_receive_network_id.get_destination_id(),
       
   354 			m_receive_network_id.get_source_id(),
       
   355 			m_receive_network_id.get_type());
       
   356 
       
   357 		eap_status_e status = m_partner->asynchronous_init_remove_eap_session(
       
   358 			&send_network_id);
       
   359 
       
   360 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   361 }
       
   362 
       
   363 //--------------------------------------------------
       
   364 
       
   365 //
       
   366 eap_status_e eap_core_c::init_end_of_session(
       
   367 	const abs_eap_state_notification_c * const state)
       
   368 {
       
   369 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   370 
       
   371 	EAP_TRACE_DEBUG(
       
   372 		m_am_tools, 
       
   373 		TRACE_FLAGS_DEFAULT, 
       
   374 		(EAPL("eap_core_c::init_end_of_session(): %s.\n"),
       
   375 		 (m_is_client == true) ? "client": "server"));
       
   376 
       
   377 	eap_status_e status(eap_status_process_general_error);
       
   378 
       
   379 	// Normally we will remove session after authentication ends.
       
   380 	// Remove session only if the stack is not already being deleted
       
   381 	if (m_shutdown_was_called == false)
       
   382 	{
       
   383 		#if defined(USE_EAPOL_KEY_STATE) && defined(USE_EAP_CORE_RESTART_AUTHENTICATION)
       
   384 			#error ERROR: USE_EAPOL_KEY_STATE and USE_EAP_CORE_RESTART_AUTHENTICATION cannot be used same time.
       
   385 		#endif //#if defined(USE_EAPOL_KEY_STATE) && defined(USE_EAP_CORE_RESTART_AUTHENTICATION)
       
   386 
       
   387 		#if defined(USE_EAP_CORE_SIMULATOR_VERSION) && defined(USE_EAP_CORE_RESTART_AUTHENTICATION)
       
   388 
       
   389 			// Simulator reuses current session.
       
   390 			status = restart_authentication(
       
   391 				state->get_send_network_id(),
       
   392 				m_is_client);
       
   393 			if (status != eap_status_ok)
       
   394 			{
       
   395 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   396 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   397 			}
       
   398 
       
   399 		#elif defined(USE_EAP_CORE_SIMULATOR_VERSION) && defined(USE_EAPOL_KEY_STATE)
       
   400 
       
   401 			EAP_TRACE_DEBUG(
       
   402 				m_am_tools,
       
   403 				TRACE_FLAGS_DEFAULT,
       
   404 				(EAPL("eap_core_c::state_notification(): %s, %s, Ignored notification: ")
       
   405 				 EAPL("Protocol layer %d, EAP type 0x%02x, State transition from ")
       
   406 				 EAPL("%d=%s to %d=%s, client %d.\n"),
       
   407 				 (m_is_client == true) ? "client": "server",
       
   408 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   409 				 state->get_protocol_layer(), 
       
   410 				 state->get_protocol(), 
       
   411 				 state->get_previous_state(), 
       
   412 				 state->get_previous_state_string(), 
       
   413 				 state->get_current_state(), 
       
   414 				 state->get_current_state_string(),
       
   415 				 state->get_is_client()));
       
   416 
       
   417 		#endif //#if defined(USE_EAP_CORE_SIMULATOR_VERSION)
       
   418 
       
   419 		status = initialize_asynchronous_init_remove_eap_session(m_remove_session_timeout);
       
   420 		if (status != eap_status_ok)
       
   421 		{
       
   422 			EAP_UNREFERENCED_PARAMETER(state);
       
   423 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   424 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   425 		}
       
   426 	}
       
   427 	else
       
   428 	{
       
   429 		EAP_TRACE_DEBUG(
       
   430 			m_am_tools,
       
   431 			TRACE_FLAGS_DEFAULT,
       
   432 			(EAPL("eap_core_c::state_notification(): %s, %s, Ignored notification: ")
       
   433 			 EAPL("Protocol layer %d, EAP type 0x%02x, State transition from ")
       
   434 			 EAPL("%d=%s to %d=%s, client %d when shutdown was called.\n"),
       
   435 			 (m_is_client == true) ? "client": "server",
       
   436 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   437 			 state->get_protocol_layer(), 
       
   438 			 state->get_protocol(), 
       
   439 			 state->get_previous_state(), 
       
   440 			 state->get_previous_state_string(), 
       
   441 			 state->get_current_state(), 
       
   442 			 state->get_current_state_string(),
       
   443 			 state->get_is_client()));
       
   444 
       
   445 		status = eap_status_ok;
       
   446 	}
       
   447 
       
   448 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   449 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   450 }
       
   451 
       
   452 //--------------------------------------------------
       
   453 
       
   454 EAP_FUNC_EXPORT void eap_core_c::state_notification(
       
   455 	const abs_eap_state_notification_c * const state)
       
   456 {
       
   457 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   458 
       
   459 	eap_status_string_c status_string;
       
   460 	eap_header_string_c eap_string;
       
   461 	EAP_UNREFERENCED_PARAMETER(status_string); // in release
       
   462 	EAP_UNREFERENCED_PARAMETER(eap_string); // in release
       
   463 
       
   464 	EAP_TRACE_DEBUG(
       
   465 		m_am_tools, 
       
   466 		TRACE_FLAGS_DEFAULT, 
       
   467 		(EAPL("eap_core_c::state_notification(), %s, %s, protocol_layer %d=%s, protocol %d=%s, EAP-type 0x%08x=%s.\n"),
       
   468 		(m_is_client == true) ? "client": "server",
       
   469 		(m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   470 		state->get_protocol_layer(),
       
   471 		state->get_protocol_layer_string(),
       
   472 		state->get_protocol(),
       
   473 		state->get_protocol_string(),
       
   474 		convert_eap_type_to_u32_t(state->get_eap_type()),
       
   475 		eap_string.get_eap_type_string(state->get_eap_type())));
       
   476 
       
   477 	EAP_TRACE_DEBUG(
       
   478 		m_am_tools, 
       
   479 		TRACE_FLAGS_DEFAULT, 
       
   480 		(EAPL("eap_core_c::state_notification(), %s, %s, current_state %d=%s, error %d=%s.\n"),
       
   481 		(m_is_client == true) ? "client": "server",
       
   482 		(m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   483 		state->get_current_state(),
       
   484 		state->get_current_state_string(),
       
   485 		state->get_authentication_error(),
       
   486 		status_string.get_status_string(state->get_authentication_error())));
       
   487 
       
   488 	if (m_ignore_notifications == true
       
   489 		|| m_partner == 0)
       
   490 	{
       
   491 		return;
       
   492 	}
       
   493 
       
   494 	// Check if the notification is from the current active type
       
   495 	if (state->get_protocol_layer() == eap_protocol_layer_general)
       
   496 	{
       
   497 		 // These notications are allowed always.
       
   498 	}
       
   499 	else if (state->get_protocol_layer() == eap_protocol_layer_eap
       
   500 		&& state->get_eap_type() != m_current_eap_type)
       
   501 	{
       
   502 		EAP_TRACE_DEBUG(
       
   503 			m_am_tools,
       
   504 			TRACE_FLAGS_DEFAULT,
       
   505 			(EAPL("eap_core_c::state_notification(): %s, %s, Ignored notification: ")
       
   506 			 EAPL("Protocol layer %d, non-active EAP type 0x%02x, current EAP type 0x%08x, State transition from ")
       
   507 			 EAPL("%d=%s to %d=%s, client %d\n"),
       
   508 			 (m_is_client == true) ? "client": "server",
       
   509 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   510 			state->get_protocol_layer(),
       
   511 			state->get_protocol(),
       
   512 			convert_eap_type_to_u32_t(m_current_eap_type),
       
   513 			state->get_previous_state(),
       
   514 			state->get_previous_state_string(),
       
   515 			state->get_current_state(),
       
   516 			state->get_current_state_string(),
       
   517 			state->get_is_client()));
       
   518 		return;
       
   519 	}
       
   520 
       
   521 	if (state->get_protocol_layer() == eap_protocol_layer_eap)
       
   522 	{
       
   523 		if (state->get_current_state() == eap_state_identity_response_received)
       
   524 		{
       
   525 			m_eap_identity_response_accepted = true;
       
   526 
       
   527 			EAP_TRACE_DEBUG(
       
   528 				m_am_tools, 
       
   529 				TRACE_FLAGS_DEFAULT, 
       
   530 				(EAPL("EAP-Response/Identity received: %s, %s\n"),
       
   531 				 (m_is_client == true) ? "client": "server",
       
   532 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
   533 				 ));
       
   534 		}
       
   535 		else if (state->get_current_state() == eap_state_identity_request_received)
       
   536 		{
       
   537 			EAP_TRACE_DEBUG(
       
   538 				m_am_tools, 
       
   539 				TRACE_FLAGS_DEFAULT, 
       
   540 				(EAPL("EAP-Request/Identity received: %s, %s\n"),
       
   541 				 (m_is_client == true) ? "client": "server",
       
   542 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
   543 				 ));
       
   544 		}
       
   545 		else if (state->get_current_state() == eap_state_authentication_terminated_unsuccessfully)
       
   546 		{
       
   547 			EAP_TRACE_DEBUG(
       
   548 				m_am_tools, 
       
   549 				TRACE_FLAGS_DEFAULT, 
       
   550 				(EAPL("ERROR: eap_core_c::state_notification(): %s, %s: EAP-authentication terminated unsuccessfully.\n"),
       
   551 				 (m_is_client == true) ? "client": "server",
       
   552 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
   553 				 ));
       
   554 
       
   555 #if defined(USE_EAP_CORE_SERVER)
       
   556 			if (m_is_client == false
       
   557 				&& (m_eap_type_response_sent == true
       
   558 					|| m_eap_identity_response_received == true)
       
   559 				&& m_send_eap_success_after_notification == false)
       
   560 			{
       
   561 				/**
       
   562 				 * 2003-10-01 draft-ietf-eap-rfc2284bis-06.txt chapter 2.
       
   563 				 * Extensible Authentication Protocol (EAP):
       
   564 				 * The authenticator MUST NOT send a Success or Failure packet when retransmitting
       
   565 				 * or when it fails to get a response from the peer.
       
   566 				 * In the case eap_state_authentication_terminated_unsuccessfully we will need a flag
       
   567 				 * that indicates whether there was a response from client or not.
       
   568 				 * If there was a response server must send EAP-Failure.
       
   569 				 * If there was NO response from client server
       
   570 				 * does NOT send EAP-Failure.
       
   571 				 */
       
   572 				send_eap_failure(
       
   573 					state->get_send_network_id(),
       
   574 					state->get_eap_identifier());
       
   575 			}
       
   576 #endif //#if defined(USE_EAP_CORE_SERVER)
       
   577 
       
   578 			(void) init_end_of_session(state);
       
   579 		}
       
   580 		else if (state->get_current_state() == eap_state_authentication_finished_successfully)
       
   581 		{
       
   582 			EAP_TRACE_DEBUG(
       
   583 				m_am_tools, 
       
   584 				TRACE_FLAGS_DEFAULT, 
       
   585 				(EAPL("eap_core_c::state_notification(): %s, %s: EAP-authentication finished successfully.\n"),
       
   586 				 (m_is_client == true) ? "client": "server",
       
   587 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
   588 				 ));
       
   589 
       
   590 
       
   591 #if defined(USE_EAP_CORE_SERVER)
       
   592 			if (m_is_client == false
       
   593 				&& m_eap_type_response_sent == true
       
   594 				&& m_send_eap_success_after_notification == false)
       
   595 			{
       
   596 				// Here we test whether the EAP-type allow send EAP-Success.
       
   597 				// For example PEAP v1 does not allow send EAP-Success.
       
   598 				if (state->get_allow_send_eap_success() == true)
       
   599 				{
       
   600 					send_eap_success(
       
   601 						state->get_send_network_id(),
       
   602 						state->get_eap_identifier());
       
   603 				}
       
   604 
       
   605 				// Now we can send a new EAP-Request/Identity.
       
   606 				m_eap_identity_request_send = false;
       
   607 			}
       
   608 #endif //#if defined(USE_EAP_CORE_SERVER)
       
   609 
       
   610 			(void) init_end_of_session(state);
       
   611 		}
       
   612 		else if (m_is_client == true
       
   613 			&& state->get_current_state() == eap_state_use_eap_failure_in_termination)
       
   614 		{
       
   615 			// Client should accept EAP-Failure quietly.
       
   616 			m_ignore_eap_failure = true;
       
   617 
       
   618 			(void) init_end_of_session(state);
       
   619 		}
       
   620 #if defined(USE_EAP_CORE_SERVER)
       
   621 		else if (m_is_client == false
       
   622 			&& state->get_current_state() == eap_state_use_eap_failure_in_termination)
       
   623 		{
       
   624 			send_eap_failure(
       
   625 				state->get_send_network_id(),
       
   626 				state->get_eap_identifier());
       
   627 
       
   628 			(void) init_end_of_session(state);
       
   629 		}
       
   630 		else if (m_current_eap_type == eap_type_peap
       
   631 			&& state->get_current_state() == eap_state_authentication_wait_tppd_peapv1_empty_acknowledge)
       
   632 		{
       
   633 			send_eap_success(
       
   634 				state->get_send_network_id(),
       
   635 				state->get_eap_identifier());
       
   636 
       
   637 			return;
       
   638 		}
       
   639 #endif //#if defined(USE_EAP_CORE_SERVER)
       
   640 	}
       
   641 
       
   642 
       
   643 	m_partner->state_notification(state);
       
   644 
       
   645 
       
   646 #if defined(USE_EAP_CORE_SERVER)
       
   647 	// EAP-Success is send after the success notification is forwarded to lower layer.
       
   648 	// This allows to combine success notification and sent EAP-success packet.
       
   649 	if (state->get_current_state() == eap_state_authentication_finished_successfully)
       
   650 	{
       
   651 		if (m_is_client == false
       
   652 			&& m_eap_type_response_sent == true
       
   653 			&& m_send_eap_success_after_notification == true)
       
   654 		{
       
   655 			// Here we test whether the EAP-type allow send EAP-Success.
       
   656 			// For example PEAP v1 does not allow send EAP-Success.
       
   657 			if (state->get_allow_send_eap_success() == true)
       
   658 			{
       
   659 				send_eap_success(
       
   660 					state->get_send_network_id(),
       
   661 					state->get_eap_identifier());
       
   662 			}
       
   663 			
       
   664 			// Now we can send a new EAP-Request/Identity.
       
   665 			m_eap_identity_request_send = false;
       
   666 		}
       
   667 	}
       
   668 	else if (state->get_current_state() == eap_state_authentication_terminated_unsuccessfully)
       
   669 	{
       
   670 		if (m_is_client == false
       
   671 			&& (m_eap_type_response_sent == true
       
   672 				|| m_eap_identity_response_received == true)
       
   673 			&& m_send_eap_success_after_notification == true)
       
   674 		{
       
   675 			/**
       
   676 			 * 2003-10-01 draft-ietf-eap-rfc2284bis-06.txt chapter 2.
       
   677 			 * Extensible Authentication Protocol (EAP):
       
   678 			 * The authenticator MUST NOT send a Success or Failure packet when retransmitting
       
   679 			 * or when it fails to get a response from the peer.
       
   680 			 * In the case eap_state_authentication_terminated_unsuccessfully we will need a flag
       
   681 			 * that indicates whether there was a response from client or not.
       
   682 			 * If there was a response server must send EAP-Failure.
       
   683 			 * If there was NO response from client server
       
   684 			 * does NOT send EAP-Failure.
       
   685 			 */
       
   686 			send_eap_failure(
       
   687 				state->get_send_network_id(),
       
   688 				state->get_eap_identifier());
       
   689 		}
       
   690 	}
       
   691 #endif //#if defined(USE_EAP_CORE_SERVER)
       
   692 
       
   693 
       
   694 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   695 }
       
   696 
       
   697 //--------------------------------------------------
       
   698 
       
   699 //
       
   700 EAP_FUNC_EXPORT eap_base_type_c * eap_core_c::load_type(
       
   701 	const eap_type_value_e type,
       
   702 	const eap_type_value_e tunneling_type,
       
   703 	const eap_am_network_id_c * const receive_network_id)
       
   704 {
       
   705 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   706 
       
   707 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
   708 
       
   709 	eap_base_type_c *handler = 0;
       
   710 
       
   711 	eap_status_e status = m_partner->load_module(
       
   712 		type,
       
   713 		tunneling_type,
       
   714 		this,
       
   715 		&handler,
       
   716 		m_is_client,
       
   717 		receive_network_id);
       
   718 	if (status != eap_status_ok)
       
   719 	{
       
   720 		if (handler != 0)
       
   721 		{
       
   722 			handler->shutdown();
       
   723 			delete handler;
       
   724 		}
       
   725 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   726 		return 0;
       
   727 	}
       
   728 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   729 	return handler;
       
   730 }
       
   731 
       
   732 //--------------------------------------------------
       
   733 
       
   734 EAP_FUNC_EXPORT eap_status_e eap_core_c::check_is_valid_eap_type(const eap_type_value_e eap_type)
       
   735 {
       
   736 	eap_status_e status = m_partner->check_is_valid_eap_type(eap_type);
       
   737 
       
   738 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   739 }
       
   740 
       
   741 //--------------------------------------------------
       
   742 
       
   743 EAP_FUNC_EXPORT eap_status_e eap_core_c::get_eap_type_list(
       
   744 	eap_array_c<eap_type_value_e> * const eap_type_list)
       
   745 {
       
   746 	eap_status_e status = m_partner->get_eap_type_list(eap_type_list);
       
   747 
       
   748 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   749 }
       
   750 
       
   751 //--------------------------------------------------
       
   752 
       
   753 //
       
   754 EAP_FUNC_EXPORT eap_status_e eap_core_c::initialize_session_timeout(const u32_t session_timeout_ms)
       
   755 {
       
   756 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   757 
       
   758 	cancel_session_timeout();
       
   759 
       
   760 	eap_status_e status = m_partner->set_timer(
       
   761 		this,
       
   762 		EAP_CORE_SESSION_TIMEOUT_ID,
       
   763 		0,
       
   764 		session_timeout_ms);
       
   765 
       
   766 	if (status != eap_status_ok)
       
   767 	{
       
   768 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   769 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   770 	}
       
   771 
       
   772 	EAP_TRACE_DEBUG(
       
   773 		m_am_tools, 
       
   774 		TRACE_FLAGS_DEFAULT, 
       
   775 		(EAPL("TIMER: %s: %s, EAP_CORE_SESSION_TIMEOUT_ID set %d ms, this = 0x%08x.\n"),
       
   776 		 (m_is_client == true) ? "client": "server",
       
   777 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   778 		 session_timeout_ms,
       
   779 		 this));
       
   780 
       
   781 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   782 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   783 }
       
   784 
       
   785 //--------------------------------------------------
       
   786 
       
   787 EAP_FUNC_EXPORT eap_status_e eap_core_c::cancel_session_timeout()
       
   788 {
       
   789 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   790 
       
   791 	eap_status_e status = m_partner->cancel_timer(
       
   792 		this,
       
   793 		EAP_CORE_SESSION_TIMEOUT_ID);
       
   794 	
       
   795 	EAP_UNREFERENCED_PARAMETER(status); // in release
       
   796 	
       
   797 	EAP_TRACE_DEBUG(
       
   798 		m_am_tools, 
       
   799 		TRACE_FLAGS_DEFAULT, 
       
   800 		(EAPL("TIMER: %s: %s, EAP_CORE_SESSION_TIMEOUT_ID cancelled status %d, this = 0x%08x.\n"),
       
   801 		 (m_is_client == true ? "client": "server"),
       
   802 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   803 		 status,
       
   804 		 this));
       
   805 
       
   806 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   807 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   808 }
       
   809 
       
   810 //--------------------------------------------------
       
   811 
       
   812 EAP_FUNC_EXPORT void eap_core_c::trace_eap_packet(
       
   813 	eap_const_string prefix,
       
   814 	const eap_header_wr_c * const eap_header)
       
   815 {
       
   816 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   817 
       
   818 	// Get rid of warnings in release version
       
   819 	EAP_UNREFERENCED_PARAMETER(eap_header);
       
   820 	EAP_UNREFERENCED_PARAMETER(prefix);
       
   821 
       
   822 	EAP_TRACE_DEBUG(
       
   823 		m_am_tools, 
       
   824 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
   825 		(EAPL("%s EAP_Core: %s, %s, code=0x%02x=%s, identifier=0x%02x, length=0x%04x, type=0x%08x=%s, packet length 0x%04x\n"),
       
   826 		prefix,
       
   827 		(m_is_client == true) ? "client": "server",
       
   828 		(m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
   829 		eap_header->get_code(),
       
   830 		eap_header->get_code_string(),
       
   831 		eap_header->get_identifier(),
       
   832 		eap_header->get_length(),
       
   833 		convert_eap_type_to_u32_t(eap_header->get_type()),
       
   834 		eap_header->get_type_string(),
       
   835 		eap_header->get_length()));
       
   836 }
       
   837 
       
   838 
       
   839 //--------------------------------------------------
       
   840 
       
   841 #if defined(USE_EAP_CORE_SERVER)
       
   842 
       
   843 EAP_FUNC_EXPORT eap_status_e eap_core_c::restart_with_new_type(
       
   844 	const eap_type_value_e used_eap_type,
       
   845 	const eap_am_network_id_c * const receive_network_id,
       
   846 	const u8_t eap_identifier)
       
   847 {
       
   848 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   849 
       
   850 	EAP_TRACE_DEBUG(
       
   851 		m_am_tools, 
       
   852 		TRACE_FLAGS_DEFAULT, 
       
   853 		(EAPL("eap_core_c::restart_with_new_type(): %s\n"),
       
   854 		(m_is_client == true) ? "client": "server"));
       
   855 
       
   856 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_core_c::restart_with_new_type()");
       
   857 
       
   858 	// Here we need to re-create the received EAP-Response/Identity message.
       
   859 
       
   860 	if (m_eap_identity.get_is_valid_data() == false)
       
   861 	{
       
   862 		// No saved EAP-Identity. Cannot continue.
       
   863 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   864 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
   865 	}
       
   866 
       
   867 	eap_status_e status = eap_status_process_general_error;
       
   868 
       
   869 	eap_buf_chain_wr_c response_packet(
       
   870 		eap_write_buffer, 
       
   871 		m_am_tools, 
       
   872 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
   873 
       
   874 	if (response_packet.get_is_valid() == false)
       
   875 	{
       
   876 		EAP_TRACE_ERROR(
       
   877 			m_am_tools, 
       
   878 			TRACE_FLAGS_DEFAULT, 
       
   879 			(EAPL("packet buffer corrupted: %s, %s\n"),
       
   880 			 (m_is_client == true) ? "client": "server",
       
   881 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
   882 			 ));
       
   883 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   884 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   885 	}
       
   886 
       
   887 	status = create_eap_identity_response(
       
   888 		&response_packet,
       
   889 		&m_eap_identity,
       
   890 		eap_identifier);
       
   891 	if (status != eap_status_ok)
       
   892 	{
       
   893 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   894 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   895 	}
       
   896 
       
   897 
       
   898 	eap_header_wr_c eap(
       
   899 		m_am_tools,
       
   900 		response_packet.get_data_offset(m_eap_header_offset, response_packet.get_data_length()),
       
   901 		response_packet.get_data_length());
       
   902 	if (eap.get_is_valid() == false)
       
   903 	{
       
   904 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   905 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   906 	}
       
   907 
       
   908 	// Bacause we start with a new EAP-type EAP-Response/Identity is prosessed again.
       
   909 	m_eap_identity_response_accepted = false;
       
   910 
       
   911 	m_ignore_eap_failure = false;
       
   912 
       
   913 	status = packet_process_type(
       
   914 		used_eap_type,
       
   915 		receive_network_id,
       
   916 		&eap,
       
   917 		eap.get_length());
       
   918 
       
   919 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   920 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   921 }
       
   922 
       
   923 #endif //#if defined(USE_EAP_CORE_SERVER)
       
   924 
       
   925 //--------------------------------------------------
       
   926 
       
   927 EAP_FUNC_EXPORT eap_status_e eap_core_c::client_proposes_eap_types(
       
   928 	const eap_am_network_id_c * const receive_network_id,
       
   929 	const u8_t eap_identifier)
       
   930 {
       
   931 	eap_array_c<eap_type_value_e> eap_type_list(m_am_tools);
       
   932 
       
   933 	/**
       
   934 	 * @{ 2005-04-19 complete Expanded Nak Type to client_proposes_eap_types(). }
       
   935 	 */
       
   936 	eap_status_e status = get_eap_type_list(&eap_type_list);
       
   937 	if (status != eap_status_ok)
       
   938 	{
       
   939 		eap_type_list.reset();
       
   940 
       
   941 		eap_type_value_e * default_eap_type = new eap_type_value_e(m_default_eap_type);
       
   942 		if (default_eap_type == 0)
       
   943 		{
       
   944 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   945 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   946 		}
       
   947 
       
   948 		status = eap_type_list.add_object(default_eap_type, true);
       
   949 		if (status != eap_status_ok)
       
   950 		{
       
   951 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   952 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   953 		}
       
   954 	}
       
   955 
       
   956 	status = send_eap_nak_response(
       
   957 		receive_network_id,
       
   958 		eap_identifier,
       
   959 		&eap_type_list);
       
   960 
       
   961 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   962 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   963 }
       
   964 
       
   965 //--------------------------------------------------
       
   966 
       
   967 EAP_FUNC_EXPORT eap_status_e eap_core_c::packet_process_type(
       
   968 	const eap_type_value_e used_eap_type,
       
   969 	const eap_am_network_id_c * const receive_network_id,
       
   970 	eap_general_header_base_c * const packet_data,
       
   971 	const u32_t packet_length)
       
   972 {
       
   973 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   974 
       
   975 	EAP_TRACE_DEBUG(
       
   976 		m_am_tools, 
       
   977 		TRACE_FLAGS_DEFAULT, 
       
   978 		(EAPL("eap_core_c::packet_process_type(): %s\n"),
       
   979 		(m_is_client == true) ? "client": "server"));
       
   980 
       
   981 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_core_c::packet_process_type()");
       
   982 
       
   983 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
   984 
       
   985 	if (packet_data == 0)
       
   986 	{
       
   987 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   988 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   989 	}
       
   990 
       
   991 	if (packet_length < eap_header_base_c::get_header_length())
       
   992 	{
       
   993 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   994 		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
       
   995 	}
       
   996 
       
   997 	eap_header_wr_c eap(
       
   998 		m_am_tools,
       
   999 		packet_data->get_header_buffer(packet_data->get_header_buffer_length()),
       
  1000 		packet_data->get_header_buffer_length());
       
  1001 
       
  1002 	if (eap.get_is_valid() == false)
       
  1003 	{
       
  1004 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1005 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1006 	}
       
  1007 
       
  1008 	if (packet_length < eap.get_length())
       
  1009 	{
       
  1010 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1011 		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
       
  1012 	}
       
  1013 
       
  1014 	if (eap.get_code() == eap_code_none)
       
  1015 	{
       
  1016 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1017 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1018 	}
       
  1019 
       
  1020 	EAP_TRACE_DEBUG(
       
  1021 		m_am_tools, 
       
  1022 		TRACE_TEST_VECTORS, 
       
  1023 		(EAPL("--------------------------------------------------------\n")));
       
  1024 
       
  1025 	eap_status_e status = eap.check_header();
       
  1026 	if (status != eap_status_ok)
       
  1027 	{
       
  1028 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1029 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1030 	}
       
  1031 
       
  1032 
       
  1033 
       
  1034 	status = eap_status_process_general_error;
       
  1035 
       
  1036 	if (m_eap_type_response_sent == false
       
  1037 		&& m_current_eap_type != used_eap_type)
       
  1038 	{
       
  1039 		status = check_is_valid_eap_type(used_eap_type);
       
  1040 		if (status != eap_status_ok)
       
  1041 		{
       
  1042 			if (m_is_client_role == true)
       
  1043 			{
       
  1044 				// Client does not accept proposed EAP type.
       
  1045 				// We must send EAP-Response/Nak message with list of our own preferred EAP-Types.
       
  1046 				status = client_proposes_eap_types(
       
  1047 					receive_network_id,
       
  1048 					eap.get_identifier());
       
  1049 
       
  1050 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1051 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1052 			} 
       
  1053 			else 
       
  1054 			{
       
  1055 				// Not acceptable EAP-type in the server.
       
  1056 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1057 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1058 			}
       
  1059 		}
       
  1060 
       
  1061 		// Now the current EAP-type is used_eap_type.
       
  1062 
       
  1063 		// First remove current EAP-type.
       
  1064 		eap_variable_data_c selector(m_am_tools);
       
  1065 		status = selector.set_copy_of_buffer(&m_current_eap_type, sizeof(m_current_eap_type));
       
  1066 		if (status != eap_status_ok)
       
  1067 		{
       
  1068 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1069 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1070 		}
       
  1071 		eap_base_type_c *handler = m_type_map.get_handler(&selector);
       
  1072 
       
  1073 		// Change the current EAP-type here because shutdown could cause state notifications from old EAP-type.
       
  1074 		m_current_eap_type = used_eap_type;
       
  1075 
       
  1076 		if (handler != 0)
       
  1077 		{
       
  1078 			status = handler->shutdown();
       
  1079 			if (status != eap_status_ok)
       
  1080 			{
       
  1081 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1082 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1083 			}
       
  1084 
       
  1085 			status = m_type_map.remove_handler(&selector, true);
       
  1086 			if (status != eap_status_ok)
       
  1087 			{
       
  1088 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1089 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1090 			}
       
  1091 		}
       
  1092 	}
       
  1093 
       
  1094 	// Here we query the desired EAP-type.
       
  1095 	eap_variable_data_c selector(m_am_tools);
       
  1096 	u64_t selector_eap_type = convert_eap_type_to_u64_t(used_eap_type);
       
  1097 	status = selector.set_buffer(&selector_eap_type, sizeof(selector_eap_type), false, false);
       
  1098 	if (status != eap_status_ok)
       
  1099 	{
       
  1100 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1101 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1102 	}
       
  1103 	eap_base_type_c *handler = m_type_map.get_handler(&selector);
       
  1104 	
       
  1105 	// Check if we already have this type loaded.
       
  1106 	if (handler == 0)
       
  1107 	{
       
  1108 		// No. Load it.
       
  1109 		if (m_eap_type_response_sent == false
       
  1110 			&& eap.get_type() != eap_type_identity
       
  1111 			&& (eap.get_code() == eap_code_request
       
  1112 				|| eap.get_code() == eap_code_response))
       
  1113 		{
       
  1114 			// Here we need a check that proposed EAP type is valid for us.
       
  1115 			status = check_is_valid_eap_type(used_eap_type);
       
  1116 			if (status != eap_status_ok)
       
  1117 			{
       
  1118 				if (m_is_client_role == true)
       
  1119 				{
       
  1120 					// Client does not accept proposed EAP type.
       
  1121 					// We must send EAP-Response/Nak message with list of our own preferred EAP-Types.
       
  1122 					status = client_proposes_eap_types(
       
  1123 						receive_network_id,
       
  1124 						eap.get_identifier());
       
  1125 
       
  1126 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1127 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1128 				} 
       
  1129 				else 
       
  1130 				{
       
  1131 					// Not acceptable EAP-type in the server.
       
  1132 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1133 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1134 				}
       
  1135 			}
       
  1136 			// Change the current eap type.
       
  1137 			m_current_eap_type = used_eap_type;
       
  1138 		}
       
  1139 		else if (eap.get_code() == eap_code_success
       
  1140 				|| eap.get_code() == eap_code_failure)
       
  1141 		{
       
  1142 			// EAP-Success or EAP-Failure is not allowed at this state.
       
  1143 			// This packet is dropped quietly.
       
  1144 			EAP_TRACE_DEBUG(
       
  1145 				m_am_tools, 
       
  1146 				TRACE_FLAGS_DEFAULT, 
       
  1147 				(EAPL("WARNING: eap_core_c::packet_process_type(): %s, %s, drops %s quietly.\n"),
       
  1148 				 (m_is_client_role == true) ? "client": "server",
       
  1149 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1150 				 eap.get_code_string()
       
  1151 				 ));
       
  1152 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1153 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1154 		}
       
  1155 		else if (m_eap_type_response_sent == false
       
  1156 			&& eap.get_type() == eap_type_identity
       
  1157 			&& (eap.get_code() == eap_code_request
       
  1158 				|| eap.get_code() == eap_code_response))
       
  1159 		{
       
  1160 			// EAP-Request/Identity is allowed at this state.
       
  1161 			EAP_ASSERT(used_eap_type != eap_type_none);
       
  1162 		}
       
  1163 		else
       
  1164 		{
       
  1165 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1166 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1167 		}
       
  1168 
       
  1169 		// A new EAP-type is needed. The load_type() allocates new object.
       
  1170 		handler = load_type(
       
  1171 			used_eap_type,
       
  1172 			eap_type_none,
       
  1173 			receive_network_id);
       
  1174 		if (handler != 0
       
  1175 			&& handler->get_is_valid() == true)
       
  1176 		{
       
  1177 			status = handler->configure();
       
  1178 			if (status != eap_status_ok)
       
  1179 			{
       
  1180 				handler->shutdown();
       
  1181 				delete handler;
       
  1182 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1183 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1184 			}
       
  1185 
       
  1186 			status = m_type_map.add_handler(&selector, handler);
       
  1187 			if (status != eap_status_ok)
       
  1188 			{
       
  1189 				handler->shutdown();
       
  1190 				delete handler;
       
  1191 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1192 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1193 			}
       
  1194 		}
       
  1195 		else
       
  1196 		{
       
  1197 			if (handler != 0)
       
  1198 			{
       
  1199 				// Handler not constructed successfully.
       
  1200 				handler->shutdown();
       
  1201 				delete handler;
       
  1202 				status = eap_status_allocation_error;
       
  1203 			}
       
  1204 			else
       
  1205 			{
       
  1206 				status = eap_status_type_does_not_exists_error;
       
  1207 			}
       
  1208 
       
  1209 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1210 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1211 		}
       
  1212 	} 
       
  1213 
       
  1214 #if defined(USE_EAP_CORE_SERVER)
       
  1215 	// We now have handler. Process packet
       
  1216 	if (m_nak_process_timer_active == true)
       
  1217 	{
       
  1218 		m_partner->cancel_timer(
       
  1219 			this,
       
  1220 			EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID);
       
  1221 
       
  1222 		EAP_TRACE_DEBUG(
       
  1223 			m_am_tools, 
       
  1224 			TRACE_FLAGS_DEFAULT, 
       
  1225 			(EAPL("TIMER: %s: %s, EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID cancelled, this = 0x%08x.\n"),
       
  1226 			 (m_is_client_role == true ? "client": "server"),
       
  1227 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1228 			 this));
       
  1229 
       
  1230 		m_nak_process_timer_active = false;
       
  1231 	}
       
  1232 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  1233 
       
  1234 
       
  1235 	if (m_is_client_role == true
       
  1236 		&& eap.get_code() == eap_code_request
       
  1237 		&& (eap.get_type() == eap_type_identity
       
  1238 			|| eap.get_type() == eap_type_notification))
       
  1239 	{
       
  1240 		// Client handles this packet, which is EAP-Request/Identity or EAP-Request/Notification.
       
  1241 
       
  1242 		if (eap.get_type() == eap_type_identity)
       
  1243 		{
       
  1244 			status = handle_eap_identity_request(
       
  1245 				used_eap_type,
       
  1246 				eap.get_identifier(),
       
  1247 				receive_network_id);
       
  1248 		}
       
  1249 		else if (eap.get_type() == eap_type_notification)
       
  1250 		{
       
  1251 			// Here we swap the addresses.
       
  1252 			eap_am_network_id_c send_network_id(m_am_tools,
       
  1253 				receive_network_id->get_destination_id(),
       
  1254 				receive_network_id->get_source_id(),
       
  1255 				receive_network_id->get_type());
       
  1256 
       
  1257 			/**
       
  1258 			 * @{ 2003-10-02 draft-ietf-eap-rfc2284bis-06.txt chapter 5.2 Notification:
       
  1259 			 * The peer SHOULD display this message to the user or log it if it
       
  1260 			 * cannot be displayed.  The Notification Type is intended to provide
       
  1261 			 * an acknowledged notification of some imperative nature, but it is
       
  1262 			 * not an error indication, and therefore does not change the state
       
  1263 			 * of the peer.  Examples include a password with an expiration time
       
  1264 			 * that is about to expire, an OTP sequence integer which is nearing
       
  1265 			 * 0, an authentication failure warning, etc.  In most circumstances,
       
  1266 			 * Notification should not be required.
       
  1267 			 * }
       
  1268 			 */
       
  1269 			status = send_eap_notification_response(
       
  1270 				&send_network_id,
       
  1271 				eap.get_identifier());
       
  1272 		}
       
  1273 	}
       
  1274 #if defined(USE_EAP_CORE_SERVER)
       
  1275 	else if (m_is_client_role == false
       
  1276 		&& eap.get_code() == eap_code_response
       
  1277 		&& eap.get_type() == eap_type_identity)
       
  1278 	{
       
  1279 		// Server handles this EAP-Response/Identity packet.
       
  1280 
       
  1281 		if (m_eap_identity_response_accepted == false)
       
  1282 		{
       
  1283 			m_eap_identity_response_received = true;
       
  1284 
       
  1285 			status = handle_eap_identity_response(
       
  1286 				handler,
       
  1287 				used_eap_type,
       
  1288 				receive_network_id,
       
  1289 				&eap,
       
  1290 				packet_length);
       
  1291 
       
  1292 			EAP_GENERAL_HEADER_COPY_ERROR_PARAMETERS(packet_data, &eap);
       
  1293 		}
       
  1294 		else
       
  1295 		{
       
  1296 			// Do not accept multiple EAP-Response/Identity messages.
       
  1297 			EAP_TRACE_DEBUG(
       
  1298 				m_am_tools, 
       
  1299 				TRACE_FLAGS_DEFAULT, 
       
  1300 				(EAPL("WARNING: EAP_Core: %s,%s, packet dropped quietly. m_eap_type_response_sent %d, ")
       
  1301 				 EAPL("EAP-Type 0x%08x, m_current_eap_type 0x%08x\n"),
       
  1302 				 (m_is_client_role == true) ? "client": "server",
       
  1303 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1304 				 m_eap_type_response_sent,
       
  1305 				 convert_eap_type_to_u32_t(eap.get_type()),
       
  1306 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  1307 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1308 			return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  1309 		}
       
  1310 	}
       
  1311 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  1312 	else if ((eap.get_code() == eap_code_request
       
  1313 				|| eap.get_code() == eap_code_response)
       
  1314 			&& eap.get_type() == used_eap_type
       
  1315 		|| eap.get_code() == eap_code_success
       
  1316 		|| eap.get_code() == eap_code_failure)
       
  1317 	{
       
  1318 		// Client and server handles this packet.
       
  1319 		// Packet is EAP-Request, EAP-Response, EAP-Success or EAP-Failure.
       
  1320 		// EAP-Request and EAP-Response must be of the used EAP-type.
       
  1321 
       
  1322 		if (m_is_client_role == false)
       
  1323 		{
       
  1324 			// Server received EAP-Response from client.
       
  1325 			// Now server could send EAP-Failure or EAP-success to client.
       
  1326 			// See draft-ietf-eap-rfc2284bis-06.txt chapter 2. Extensible Authentication Protocol (EAP).
       
  1327 			if (m_eap_type_response_sent == false)
       
  1328 			{
       
  1329 				// Here we swap the addresses.
       
  1330 				eap_am_network_id_c send_network_id(m_am_tools,
       
  1331 					receive_network_id->get_destination_id(),
       
  1332 					receive_network_id->get_source_id(),
       
  1333 					receive_network_id->get_type());
       
  1334 
       
  1335 				// Send state change notification
       
  1336 				eap_state_notification_c notification(
       
  1337 					m_am_tools,
       
  1338 					&send_network_id,
       
  1339 					m_is_client,
       
  1340 					eap_state_notification_eap,
       
  1341 					eap_protocol_layer_eap,
       
  1342 					m_current_eap_type,
       
  1343 					eap_state_none,
       
  1344 					eap_state_eap_response_sent,
       
  1345 					eap.get_identifier(),
       
  1346 					false);
       
  1347 				state_notification(&notification);
       
  1348 			}
       
  1349 			m_eap_type_response_sent = true;
       
  1350 		}
       
  1351 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  1352 		else
       
  1353 		{
       
  1354 			if (eap.get_code() == eap_code_request
       
  1355 				&& m_is_tunneled_eap == false
       
  1356 				&& m_is_client_role == true)
       
  1357 			{
       
  1358 				// We got the response. Now we let the session timer handle rest of timeout cases.
       
  1359 				cancel_wait_eap_request_type_timeout();
       
  1360 			}
       
  1361 		}
       
  1362 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  1363 
       
  1364 		if (m_ignore_eap_failure == false
       
  1365 			&& eap.get_code() == eap_code_failure)
       
  1366 		{
       
  1367 			// Set timer to delay EAP-Failure handling.
       
  1368 			// If no other packet is received session will be
       
  1369 			// terminated after timeout.
       
  1370 			set_eap_failure_timeout();
       
  1371 		}
       
  1372 		else
       
  1373 		{
       
  1374 			cancel_eap_failure_timeout();
       
  1375 		}
       
  1376 
       
  1377 		status = handler->packet_process(
       
  1378 			receive_network_id,
       
  1379 			&eap,
       
  1380 			packet_length);
       
  1381 
       
  1382 		EAP_GENERAL_HEADER_COPY_ERROR_PARAMETERS(packet_data, &eap);
       
  1383 
       
  1384 		if (status == eap_status_success)
       
  1385 		{
       
  1386 			// NOTE state_notification() will send EAP-Success message.
       
  1387 		}
       
  1388 	}
       
  1389 	else
       
  1390 	{
       
  1391 		EAP_TRACE_DEBUG(
       
  1392 			m_am_tools, 
       
  1393 			TRACE_FLAGS_DEFAULT,
       
  1394 			(EAPL("ERROR: %s, %s, Illegal EAP-Code %d=0x%02x=%s, EAP-Type 0x%08x=%s\n"),
       
  1395 			 (m_is_client_role == true) ? "client": "server",
       
  1396 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1397 			 eap.get_code(),
       
  1398 			 eap.get_code(),
       
  1399 			 eap.get_code_string(),
       
  1400 			 convert_eap_type_to_u32_t(eap.get_type()),
       
  1401 			 eap.get_type_string()));
       
  1402 
       
  1403 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1404 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1405 	}
       
  1406 
       
  1407 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1408 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1409 }
       
  1410 
       
  1411 //--------------------------------------------------
       
  1412 
       
  1413 /**
       
  1414  * @{ 2003-10-01 draft-ietf-eap-rfc2284bis-06.txt chapter 2.1 Support for sequences:
       
  1415  * An EAP conversation MAY utilize a sequence of methods.  A common
       
  1416  * example of this is an Identity request followed by a single EAP
       
  1417  * authentication method such as an MD5-Challenge.  However the peer and
       
  1418  * authenticator MUST utilize only one authentication method (Type 4 or
       
  1419  * greater) within an EAP conversation, after which the authenticator
       
  1420  * MUST send a Success or Failure packet.
       
  1421  * Once a peer has sent a Response of the same Type as the initial
       
  1422  * Request, an authenticator MUST NOT send a Request of a different Type
       
  1423  * prior to completion of the final round of a given method (with the
       
  1424  * exception of a Notification-Request) and MUST NOT send a Request for
       
  1425  * an additional method of any Type after completion of the initial
       
  1426  * authentication method; a peer receiving such Requests MUST treat them
       
  1427  * as invalid, and silently discard them. As a result, Identity Requery
       
  1428  * is not supported.
       
  1429  * A peer MUST NOT send a Nak (legacy or expanded) in reply to a
       
  1430  * Request, after an initial non-Nak Response has been sent.  Since
       
  1431  * spoofed EAP Request packets may be sent by an attacker, an
       
  1432  * authenticator receiving an unexpected Nak SHOULD discard it and log
       
  1433  * the event.
       
  1434  * Multiple authentication methods within an EAP conversation are not
       
  1435  * supported due to their vulnerability to man-in-the-middle attacks
       
  1436  * (see Section 7.4) and incompatibility with existing implementations.
       
  1437  * }
       
  1438  */
       
  1439 EAP_FUNC_EXPORT eap_status_e eap_core_c::packet_process(
       
  1440 	const eap_am_network_id_c * const receive_network_id,
       
  1441 	eap_general_header_base_c * const packet_data,
       
  1442 	const u32_t packet_length)
       
  1443 {
       
  1444 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1445 
       
  1446 	EAP_TRACE_DEBUG(
       
  1447 		m_am_tools, 
       
  1448 		TRACE_FLAGS_DEFAULT, 
       
  1449 		(EAPL("eap_core_c::packet_process(): %s\n"),
       
  1450 		(m_is_client == true) ? "client": "server"));
       
  1451 
       
  1452 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_core_c::packet_process()");
       
  1453 
       
  1454 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  1455 
       
  1456 	if (packet_data == 0
       
  1457 		|| packet_data->get_is_valid() == false)
       
  1458 	{
       
  1459 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1460 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1461 	}
       
  1462 
       
  1463 	if (receive_network_id == 0
       
  1464 		|| receive_network_id->get_is_valid_data() == false)
       
  1465 	{
       
  1466 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1467 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1468 	}
       
  1469 
       
  1470 	if (packet_length < eap_header_base_c::get_header_length())
       
  1471 	{
       
  1472 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1473 		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
       
  1474 	}
       
  1475 
       
  1476 	eap_header_wr_c eap(
       
  1477 		m_am_tools,
       
  1478 		packet_data->get_header_buffer(packet_data->get_header_buffer_length()),
       
  1479 		packet_data->get_header_buffer_length());
       
  1480 
       
  1481 	if (eap.get_is_valid() == false)
       
  1482 	{
       
  1483 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1484 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1485 	}
       
  1486 
       
  1487 	if (packet_length < eap.get_length())
       
  1488 	{
       
  1489 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1490 		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
       
  1491 	}
       
  1492 
       
  1493 	if (eap.get_code() == eap_code_none)
       
  1494 	{
       
  1495 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1496 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1497 	}
       
  1498 
       
  1499 	EAP_TRACE_DEBUG(
       
  1500 		m_am_tools, 
       
  1501 		TRACE_TEST_VECTORS, 
       
  1502 		(EAPL("--------------------------------------------------------\n")));
       
  1503 
       
  1504 	EAP_TRACE_DATA_DEBUG(
       
  1505 		m_am_tools, 
       
  1506 		EAP_TRACE_FLAGS_MESSAGE_DATA|TRACE_TEST_VECTORS, 
       
  1507 		(EAPL("EAP-packet"),
       
  1508 		 eap.get_header_buffer(packet_length),
       
  1509 		 packet_length));
       
  1510 
       
  1511 	trace_eap_packet("->", &eap);
       
  1512 
       
  1513 	eap_status_e status = eap.check_header();
       
  1514 	if (status != eap_status_ok)
       
  1515 	{
       
  1516 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1517 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1518 	}
       
  1519 
       
  1520 
       
  1521 #if defined (_DEBUG)
       
  1522 	if (m_retransmission != 0)
       
  1523 	{
       
  1524 		eap_header_string_c eap_string;
       
  1525 
       
  1526 		EAP_TRACE_DEBUG(
       
  1527 			m_am_tools, 
       
  1528 			TRACE_FLAGS_DEFAULT, 
       
  1529 			(EAPL("EAP_Core: eap_core_c::packet_process(): %s, retransmission counter %d, retrans EAP-type %s, retrans EAP-Id %d, current EAP-type %s, current EAP-Id %d, session 0x%08x.\n"),
       
  1530 			 (m_is_client_role == true) ? "client": "server",
       
  1531 			 m_retransmission->get_retransmission_counter(),
       
  1532 			 eap_string.get_eap_type_string(m_retransmission->get_eap_type()),
       
  1533 			 m_retransmission->get_eap_identifier(),
       
  1534 			 eap_string.get_eap_type_string(eap.get_type()),
       
  1535 			 eap.get_identifier(),
       
  1536 			 this));
       
  1537 	}
       
  1538 	else
       
  1539 	{
       
  1540 		EAP_TRACE_DEBUG(
       
  1541 			m_am_tools, 
       
  1542 			TRACE_FLAGS_DEFAULT, 
       
  1543 			(EAPL("EAP_Core: eap_core_c::packet_process(): %s, retransmission NULL, session 0x%08x.\n"),
       
  1544 			 (m_is_client_role == true) ? "client": "server",
       
  1545 			 this));
       
  1546 	}
       
  1547 #endif //#if defined (_DEBUG)
       
  1548 
       
  1549 
       
  1550 	if (m_is_client_role == true
       
  1551 		&& m_retransmission != 0
       
  1552 		&& m_retransmission->get_eap_type() == eap.get_type()
       
  1553 		&& m_retransmission->get_eap_identifier() == eap.get_identifier())
       
  1554 	{
       
  1555 		if (m_retransmission->get_retransmission_counter() > 0)
       
  1556 		{
       
  1557 			EAP_TRACE_DEBUG(
       
  1558 				m_am_tools, 
       
  1559 				TRACE_FLAGS_DEFAULT, 
       
  1560 				(EAPL("EAP_Core: eap_core_c::packet_process(): %s, retransmits previous packet, counter %d, session 0x%08x.\n"),
       
  1561 				 (m_is_client_role == true) ? "client": "server",
       
  1562 				 m_retransmission->get_retransmission_counter(),
       
  1563 				 this));
       
  1564 
       
  1565 			// We have the previous send EAP-packet stored.
       
  1566 			// It does match to the current query.
       
  1567 			// We could send the previous EAP-packet again.
       
  1568 			status = resend_packet(
       
  1569 				m_retransmission->get_send_network_id(),
       
  1570 				m_retransmission->get_sent_packet(),
       
  1571 				m_retransmission->get_header_offset(),
       
  1572 				m_retransmission->get_data_length(),
       
  1573 				m_retransmission->get_buffer_size(),
       
  1574 				m_retransmission->get_retransmission_counter()
       
  1575 				);
       
  1576 
       
  1577 			m_retransmission->get_next_retransmission_counter(); // This decrements the counter.
       
  1578 		}
       
  1579 		else
       
  1580 		{
       
  1581 			EAP_TRACE_DEBUG(
       
  1582 				m_am_tools, 
       
  1583 				TRACE_FLAGS_DEFAULT, 
       
  1584 				(EAPL("EAP_Core: eap_core_c::packet_process(): %s, Does not retransmit previous packet, counter %d, session 0x%08x.\n"),
       
  1585 				 (m_is_client_role == true) ? "client": "server",
       
  1586 				 m_retransmission->get_retransmission_counter(),
       
  1587 				 this));
       
  1588 
       
  1589 			status = eap_status_unexpected_message;
       
  1590 		}
       
  1591 
       
  1592 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1593 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1594 	}
       
  1595 #if defined(USE_EAP_CORE_SERVER)
       
  1596 	else if (m_is_client_role == false
       
  1597 		&& m_retransmission != 0
       
  1598 		&& m_retransmission->get_eap_type() == eap.get_type()
       
  1599 		&& m_retransmission->get_eap_identifier() > eap.get_identifier())
       
  1600 	{
       
  1601 		// Here we assume the EAP-Identifier increases. This is for testing purposes.
       
  1602 		// This packet is old response, drop it.
       
  1603 		EAP_TRACE_DEBUG(
       
  1604 			m_am_tools, 
       
  1605 			TRACE_FLAGS_DEFAULT, 
       
  1606 			(EAPL("EAP_Core: eap_core_c::packet_process(): %s, Does not process old packet, EAP-Identifier of last received response %d, EAP-Identifier of the packet %d, session 0x%08x.\n"),
       
  1607 			 (m_is_client_role == true) ? "client": "server",
       
  1608 			 m_retransmission->get_eap_identifier(),
       
  1609 			 eap.get_identifier(),
       
  1610 			 this));
       
  1611 
       
  1612 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1613 		return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
       
  1614 	}
       
  1615 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  1616 	else if (get_marked_removed() == true
       
  1617 			 && eap.get_code() != eap_code_success
       
  1618 			 && eap.get_code() != eap_code_failure)
       
  1619 	{
       
  1620 		// NOTE, this delayed reset of session is used bacause in some cases cannot be responsed
       
  1621 		// 4-Way Handshake message fast enough.
       
  1622 
       
  1623 		EAP_TRACE_DEBUG(
       
  1624 			m_am_tools, 
       
  1625 			TRACE_FLAGS_DEFAULT, 
       
  1626 			(EAPL("eap_core_c::packet_process(): %s, resets session, session 0x%08x.\n"),
       
  1627 			 (m_is_client_role == true) ? "client": "server",
       
  1628 			this));
       
  1629 
       
  1630 		unset_marked_removed();
       
  1631 
       
  1632 		reset();
       
  1633 	}
       
  1634 
       
  1635 
       
  1636 	eap_type_value_e used_eap_type = eap_type_none;
       
  1637 
       
  1638 	if (eap.get_code() == eap_code_request
       
  1639 		&& m_is_client_role == true)
       
  1640 	{
       
  1641 		// Send ID using default EAP type, this is our best quess of other peer's EAP type.
       
  1642 		// Other peer will sent the real EAP type later and we can NAK it then
       
  1643 		// and send our own EAP type.
       
  1644 		if (m_current_eap_type == eap_type_none)
       
  1645 		{
       
  1646 			// In Symbian implementation the default type is the highest priority EAP type. 
       
  1647 			// At the moment it is always used to reply to the identity request.
       
  1648 			m_current_eap_type = m_default_eap_type;
       
  1649 			used_eap_type = m_current_eap_type;
       
  1650 		}
       
  1651 
       
  1652 		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  1653 
       
  1654 		if (eap.get_length() > eap_header_base_c::get_header_length())
       
  1655 		{
       
  1656 			if (m_eap_type_response_sent == true
       
  1657 				&& eap.get_type() != m_current_eap_type)
       
  1658 			{
       
  1659 				if (eap.get_type() == eap_type_tlv_extensions)
       
  1660 				{
       
  1661 					// Send EAP-Response/Nak to show this is not supported.
       
  1662 
       
  1663 					eap_array_c<eap_type_value_e> eap_type_list(m_am_tools);
       
  1664 
       
  1665 					status = send_eap_nak_response(
       
  1666 						receive_network_id,
       
  1667 						eap.get_identifier(),
       
  1668 						&eap_type_list);
       
  1669 
       
  1670 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1671 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1672 				}
       
  1673 				else
       
  1674 				{
       
  1675 					/*
       
  1676 					 * 2003-10-01 draft-ietf-eap-rfc2284bis-06.txt chapter 2.1 Support for sequences:
       
  1677 					 * An EAP conversation MAY utilize a sequence of methods.  A common
       
  1678 					 * example of this is an Identity request followed by a single EAP
       
  1679 					 * authentication method such as an MD5-Challenge.  However the peer and
       
  1680 					 * authenticator MUST utilize only one authentication method (Type 4 or
       
  1681 					 * greater) within an EAP conversation, after which the authenticator
       
  1682 					 * MUST send a Success or Failure packet.
       
  1683 					 * Once a peer has sent a Response of the same Type as the initial
       
  1684 					 * Request, an authenticator MUST NOT send a Request of a different Type
       
  1685 					 * prior to completion of the final round of a given method (with the
       
  1686 					 * exception of a Notification-Request) and MUST NOT send a Request for
       
  1687 					 * an additional method of any Type after completion of the initial
       
  1688 					 * authentication method; a peer receiving such Requests MUST treat them
       
  1689 					 * as invalid, and silently discard them. As a result, Identity Requery
       
  1690 					 * is not supported.
       
  1691 					 */
       
  1692 					EAP_TRACE_DEBUG(
       
  1693 						m_am_tools, 
       
  1694 						TRACE_FLAGS_DEFAULT, 
       
  1695 						(EAPL("WARNING: EAP_Core: %s, %s, packet dropped quietly. m_eap_type_response_sent %d, ")
       
  1696 						 EAPL("EAP-Type 0x%08x, m_current_eap_type 0x%08x\n"),
       
  1697 						 (m_is_client_role == true) ? "client": "server",
       
  1698 						 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1699 						 m_eap_type_response_sent,
       
  1700 						 convert_eap_type_to_u32_t(eap.get_type()),
       
  1701 						 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  1702 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1703 					return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  1704 				}
       
  1705 			}
       
  1706 			else if (eap.get_type() == eap_type_identity)
       
  1707 			{
       
  1708 				// Should we respond here with another type?
       
  1709 				/**
       
  1710 				 * @{ Check if this is a re-transmission or a new request.
       
  1711 				 * If this is re-transmission respond using the same type as previously. 
       
  1712 				 * Otherwise assume that peer did not like our previous identity and 
       
  1713 				 * try another configured type.
       
  1714 				 * At the moment just try the last type that was used.
       
  1715 				 * }
       
  1716 				 */
       
  1717 				used_eap_type = m_current_eap_type;
       
  1718 			}
       
  1719 			else if (eap.get_type() == eap_type_notification)
       
  1720 			{
       
  1721 				// Here we are again on thin ice.
       
  1722 				// Best ques is the las used EAP type.
       
  1723 				used_eap_type = m_current_eap_type;
       
  1724 			}
       
  1725 			else
       
  1726 			{
       
  1727 				// Here we know what the server really wants
       
  1728 				// use this EAP-Type.
       
  1729 				used_eap_type = eap.get_type();
       
  1730 			}
       
  1731 		}
       
  1732 		else
       
  1733 		{
       
  1734 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1735 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1736 		}
       
  1737 	}
       
  1738 #if defined(USE_EAP_CORE_SERVER)
       
  1739 	else if (eap.get_code() == eap_code_response
       
  1740 		&& m_is_client_role == false)
       
  1741 	{
       
  1742 		// Received ID using some EAP type, this may be other than our current type.
       
  1743 
       
  1744 		if (m_current_eap_type == eap_type_none)
       
  1745 		{
       
  1746 			m_current_eap_type = m_default_eap_type;
       
  1747 			used_eap_type = m_default_eap_type;
       
  1748 		}
       
  1749 		else if (eap.get_length() > eap_header_base_c::get_header_length())
       
  1750 		{
       
  1751 			if (eap.get_type() == eap_type_identity)
       
  1752 			{
       
  1753 				used_eap_type = m_default_eap_type;
       
  1754 			}
       
  1755 			else
       
  1756 			{
       
  1757 				used_eap_type = eap.get_type();
       
  1758 
       
  1759 				if (used_eap_type == eap_type_nak
       
  1760 					|| eap_expanded_type_nak.get_type() == used_eap_type
       
  1761 					)
       
  1762 				{
       
  1763 					// Server received EAP-Response from client.
       
  1764 					// Now server could send EAP-Failure or EAP-success to client.
       
  1765 					// See draft-ietf-eap-rfc2284bis-06.txt chapter 2. Extensible Authentication Protocol (EAP).
       
  1766 
       
  1767 					/**
       
  1768 					 * @{ 2003-10-02 draft-ietf-eap-rfc2284bis-06.txt chapter 5.3.1 Legacy Nak:
       
  1769 					 * The legacy Nak Type is valid only in Response messages.  It is
       
  1770 					 * sent in reply to a Request where the desired authentication Type
       
  1771 					 * is unacceptable.  Authentication Types are numbered 4 and above.
       
  1772 					 * The Response contains one or more authentication Types desired by
       
  1773 					 * the Peer.  Type zero (0) is used to indicate that the sender has
       
  1774 					 * no viable alternatives, and therefore the authenticator SHOULD NOT
       
  1775 					 * send another Request after receiving a Nak Response containing a
       
  1776 					 * zero value.
       
  1777 					 * Since the legacy Nak Type is valid only in Responses and has very
       
  1778 					 * limited functionality, it MUST NOT be used as a general purpose
       
  1779 					 * error indication, such as for communication of error messages, or
       
  1780 					 * negotiation of parameters specific to a particular EAP method.
       
  1781 					 * }
       
  1782 					 */
       
  1783 
       
  1784 					/**
       
  1785 					 * @{ 2003-10-02 draft-ietf-eap-rfc2284bis-06.txt chapter 5.3.2 Expanded Nak:
       
  1786 					 * The Expanded Nak Type is valid only in Response messages.  It MUST
       
  1787 					 * be sent only in reply to a Request of Type 254 (Expanded Type)
       
  1788 					 * where the authentication Type is unacceptable.  The Expanded Nak
       
  1789 					 * Type uses the Expanded Type format itself, and the Response
       
  1790 					 * contains one or more authentication Types desired by the peer, all
       
  1791 					 * in Expanded Type format.  Type zero (0) is used to indicate that
       
  1792 					 * the sender has no viable alternatives.  The general format of the
       
  1793 					 * Expanded Type is described in Section 5.7.
       
  1794 					 * Since the Expanded Nak Type is valid only in Responses and has
       
  1795 					 * very limited functionality, it MUST NOT be used as a general
       
  1796 					 * purpose error indication, such as for communication of error
       
  1797 					 * messages, or negotiation of parameters specific to a particular
       
  1798 					 * EAP method.
       
  1799 					 * }
       
  1800 					 */
       
  1801 
       
  1802 					// Only server should receive this packet.
       
  1803 					if (eap.get_type_data_length() >= sizeof(u8_t))
       
  1804 					{
       
  1805 						// EAP-Response/Nak includes list of new proposal for EAP type.
       
  1806 						// Now we need to know does the proposed EAP type need separate identity.
       
  1807 						// In that case we must restart the authentication.
       
  1808 						// If the same identity is valid, we could continue.
       
  1809 
       
  1810 						u32_t proposal_length = eap.get_type_data_length();
       
  1811 						for (u32_t ind = 0ul; ind < proposal_length; ind++)
       
  1812 						{
       
  1813 							/**
       
  1814 							 * @{ 2005-04-19 complete Expanded Nak Type to packet_process(). }
       
  1815 							 */
       
  1816 							status = eap_expanded_type_c::read_type(
       
  1817 								m_am_tools,
       
  1818 								ind,
       
  1819 								eap.get_type_data(eap.get_type_data_length()),
       
  1820 								eap.get_type_data_length(),
       
  1821 								&used_eap_type);
       
  1822 							if (status != eap_status_ok)
       
  1823 							{
       
  1824 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1825 								return EAP_STATUS_RETURN(m_am_tools, status);
       
  1826 							}
       
  1827 
       
  1828 							// Here we need a check that proposed EAP type is valid for us.
       
  1829 							status = check_is_valid_eap_type(used_eap_type);
       
  1830 							if (status == eap_status_ok)
       
  1831 							{
       
  1832 								// Let's use this EAP-type.
       
  1833 								break;
       
  1834 							}
       
  1835 							else
       
  1836 							{
       
  1837 								used_eap_type = eap_type_none;
       
  1838 							}
       
  1839 						} // for()
       
  1840 
       
  1841 						if (used_eap_type == eap_type_none)
       
  1842 						{
       
  1843 							EAP_TRACE_DEBUG(
       
  1844 								m_am_tools,
       
  1845 								TRACE_FLAGS_DEFAULT,
       
  1846 								(EAPL("TIMER: %s: %s, EAP-Reponse/Nak did not include any valid EAp-type.\n"),
       
  1847 								 (m_is_client_role == true ? "client": "server"),
       
  1848 								 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  1849 								 ));
       
  1850 						}
       
  1851 
       
  1852 						// Here we swap the addresses.
       
  1853 						eap_am_network_id_c send_network_id(m_am_tools,
       
  1854 							receive_network_id->get_destination_id(),
       
  1855 							receive_network_id->get_source_id(),
       
  1856 							receive_network_id->get_type());
       
  1857 
       
  1858 						if (m_process_eap_nak_immediately == true)
       
  1859 						{
       
  1860 							if (used_eap_type == eap_type_none)
       
  1861 							{
       
  1862 								// No acceptable EAP-type.
       
  1863 								// Send a EAP-Failure.
       
  1864 								status = send_eap_failure(
       
  1865 									&send_network_id,
       
  1866 									static_cast<u8_t>(eap.get_identifier()+1ul));
       
  1867 
       
  1868 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1869 								return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_type);
       
  1870 							}
       
  1871 							else
       
  1872 							{
       
  1873 								// First remove current EAP-type.
       
  1874 								eap_variable_data_c selector(m_am_tools);
       
  1875 								status = selector.set_copy_of_buffer(
       
  1876 									&m_current_eap_type,
       
  1877 									sizeof(m_current_eap_type));
       
  1878 								if (status != eap_status_ok)
       
  1879 								{
       
  1880 									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1881 									return EAP_STATUS_RETURN(m_am_tools, status);
       
  1882 								}
       
  1883 								eap_base_type_c *handler = m_type_map.get_handler(&selector);
       
  1884 
       
  1885 								// Change the current EAP-type here because shutdown could
       
  1886 								// cause state notifications from old EAP-type.
       
  1887 								m_current_eap_type = used_eap_type;
       
  1888 
       
  1889 								if (handler != 0)
       
  1890 								{
       
  1891 									status = handler->shutdown();
       
  1892 									if (status != eap_status_ok)
       
  1893 									{
       
  1894 										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1895 										return EAP_STATUS_RETURN(m_am_tools, status);
       
  1896 									}
       
  1897 
       
  1898 									status = m_type_map.remove_handler(&selector, true);
       
  1899 									if (status != eap_status_ok)
       
  1900 									{
       
  1901 										EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1902 										return EAP_STATUS_RETURN(m_am_tools, status);
       
  1903 									}
       
  1904 								}
       
  1905 
       
  1906 								// Now restart authentication with proposed EAP type.
       
  1907 								status = restart_with_new_type(
       
  1908 									used_eap_type,
       
  1909 									receive_network_id,
       
  1910 									eap.get_identifier());
       
  1911 
       
  1912 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1913 								return EAP_STATUS_RETURN(m_am_tools, status);
       
  1914 							}
       
  1915 						}
       
  1916 						else //if (m_process_eap_nak_immediately == false)
       
  1917 						{
       
  1918 							status = eap_status_illegal_eap_type;
       
  1919 
       
  1920 							if (m_nak_process_timer_active == false)
       
  1921 							{
       
  1922 								eap_core_nak_info_c * const nak_info
       
  1923 									= new eap_core_nak_info_c(
       
  1924 										m_am_tools,
       
  1925 										receive_network_id,
       
  1926 										used_eap_type,
       
  1927 										eap.get_identifier());
       
  1928 
       
  1929 								status = m_partner->set_timer(
       
  1930 									this,
       
  1931 									EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID, 
       
  1932 									nak_info,
       
  1933 									EAP_CORE_DELAYED_EAP_NAK_PROCESS_TIMEOUT);
       
  1934 								if (status == eap_status_ok)
       
  1935 								{
       
  1936 									m_nak_process_timer_active = true;
       
  1937 								}
       
  1938 								else
       
  1939 								{
       
  1940 									// ERROR.
       
  1941 									// NOTE: timer queue did call timer_delete_data() function to free nak_info.
       
  1942 								}
       
  1943 
       
  1944 								EAP_TRACE_DEBUG(
       
  1945 									m_am_tools,
       
  1946 									TRACE_FLAGS_DEFAULT,
       
  1947 									(EAPL("TIMER: %s: %s, EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID set %d ms.\n"),
       
  1948 									 (m_is_client_role == true ? "client": "server"),
       
  1949 									 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1950 									 EAP_CORE_DELAYED_EAP_NAK_PROCESS_TIMEOUT
       
  1951 									 ));
       
  1952 							}
       
  1953 						}
       
  1954 
       
  1955 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1956 						return EAP_STATUS_RETURN(m_am_tools, status);						
       
  1957 
       
  1958 					} // if (eap.get_type_data_length() >= sizeof(u8_t))
       
  1959 					else
       
  1960 					{
       
  1961 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1962 						return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_type);
       
  1963 					}
       
  1964 				}
       
  1965 			}
       
  1966 		}
       
  1967 		else
       
  1968 		{
       
  1969 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1970 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1971 		}
       
  1972 	}
       
  1973 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  1974 	else if (eap.get_code() == eap_code_success
       
  1975 		|| eap.get_code() == eap_code_failure)
       
  1976 	{
       
  1977 		if (m_current_eap_type != eap_type_none)
       
  1978 		{
       
  1979 			// Here we are again on thin ice.
       
  1980 			// Use saved EAP type, this is our best quess of other peer's EAP type.
       
  1981 			// Other peer just informs status of authentication.
       
  1982 			used_eap_type = m_current_eap_type;
       
  1983 		}
       
  1984 		else
       
  1985 		{
       
  1986 			// No EAP-type loaded, drop message quietly.
       
  1987 			EAP_TRACE_DEBUG(
       
  1988 				m_am_tools, 
       
  1989 				TRACE_FLAGS_DEFAULT, 
       
  1990 				(EAPL("WARNING: EAP_Core: %s,%s, %s packet dropped quietly. m_eap_type_response_sent %d, ")
       
  1991 				 EAPL("m_current_eap_type 0x%08x\n"),
       
  1992 				 (m_is_client_role == true) ? "client": "server",
       
  1993 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  1994 				 eap.get_code_string(),
       
  1995 				 m_eap_type_response_sent,
       
  1996 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  1997 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1998 			return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  1999 		}
       
  2000 	}
       
  2001 	else
       
  2002 	{
       
  2003 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2004 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  2005 	}
       
  2006 
       
  2007 
       
  2008 	status = packet_process_type(
       
  2009 		used_eap_type,
       
  2010 		receive_network_id,
       
  2011 		packet_data,
       
  2012 		packet_length);
       
  2013 
       
  2014 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2015 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2016 }
       
  2017 
       
  2018 //--------------------------------------------------
       
  2019 
       
  2020 //
       
  2021 EAP_FUNC_EXPORT eap_status_e eap_core_c::packet_send(
       
  2022 	const eap_am_network_id_c * const send_network_id,
       
  2023 	eap_buf_chain_wr_c * const sent_packet,
       
  2024 	const u32_t header_offset,
       
  2025 	const u32_t data_length,
       
  2026 	const u32_t buffer_length)
       
  2027 {
       
  2028 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2029 
       
  2030 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2031 
       
  2032 	eap_header_wr_c eap(
       
  2033 		m_am_tools,
       
  2034 		sent_packet->get_data_offset(
       
  2035 			header_offset, data_length),
       
  2036 		data_length);
       
  2037 
       
  2038 	if (eap.get_is_valid() == false)
       
  2039 	{
       
  2040 		EAP_TRACE_ERROR(
       
  2041 			m_am_tools, 
       
  2042 			TRACE_FLAGS_DEFAULT, 
       
  2043 			(EAPL("packet_send: %s, %s, packet buffer corrupted.\n"),
       
  2044 			 (m_is_client_role == true) ? "client": "server",
       
  2045 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2046 			 ));
       
  2047 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2048 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2049 	}
       
  2050 
       
  2051 	EAP_ASSERT(header_offset < sent_packet->get_data_length());
       
  2052 	EAP_ASSERT(data_length <= sent_packet->get_data_length());
       
  2053 	EAP_ASSERT(sent_packet->get_data_length() <= buffer_length);
       
  2054 
       
  2055 	EAP_TRACE_DATA_DEBUG(
       
  2056 		m_am_tools, 
       
  2057 		EAP_TRACE_FLAGS_MESSAGE_DATA|TRACE_TEST_VECTORS, 
       
  2058 		(EAPL("EAP-packet"),
       
  2059 		 eap.get_header_buffer(data_length),
       
  2060 		 data_length));
       
  2061 
       
  2062 	trace_eap_packet("<-", &eap);
       
  2063 
       
  2064 	if (m_shutdown_was_called == true
       
  2065 		&& m_is_client_role == true)
       
  2066 	{
       
  2067 		EAP_TRACE_DEBUG(
       
  2068 			m_am_tools, 
       
  2069 			TRACE_FLAGS_DEFAULT, 
       
  2070 			(EAPL("WARNING: EAP_Core: %s,%s, eap_core_c::packet_send(): %s packet dropped quietly because shutdown was already called. m_eap_type_response_sent %d, ")
       
  2071 			 EAPL("m_current_eap_type 0x%08x\n"),
       
  2072 			 (m_is_client_role == true) ? "client": "server",
       
  2073 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2074 			 eap.get_code_string(),
       
  2075 			 m_eap_type_response_sent,
       
  2076 			 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  2077 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2078 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  2079 	}
       
  2080 
       
  2081 	EAP_TRACE_DEBUG(
       
  2082 		m_am_tools, 
       
  2083 		TRACE_TEST_VECTORS, 
       
  2084 		(EAPL("--------------------------------------------------------\n")));
       
  2085 
       
  2086 
       
  2087 	cancel_retransmission();
       
  2088 
       
  2089 	if (sent_packet->get_do_packet_retransmission() == true)
       
  2090 	{
       
  2091 		// Both EAP-client and EAP-server initializes re-transmission.
       
  2092 		// EAP-client will respond to re-transmitted EAP-request with the matching packet.
       
  2093 		// EAP-server will re-transmit the packet when timer elapses and no response is received.
       
  2094 		// Note the EAP-type could do re-transmission itself too. When EAP-type do re-transmission
       
  2095 		// itself EAP-type should set flag of re-transmission in the packet to true with the
       
  2096 		// set_do_packet_retransmission(true) function.
       
  2097 		init_retransmission(
       
  2098 			send_network_id,
       
  2099 			sent_packet,
       
  2100 			header_offset,
       
  2101 			data_length,
       
  2102 			eap.get_code(),
       
  2103 			eap.get_identifier(),
       
  2104 			eap.get_type());
       
  2105 	}
       
  2106 
       
  2107 
       
  2108 	eap_status_e status = m_partner->packet_send(
       
  2109 		send_network_id, sent_packet, header_offset, data_length, buffer_length);
       
  2110 	if (status != eap_status_ok)
       
  2111 	{
       
  2112 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2113 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2114 	}
       
  2115 
       
  2116 	if (m_is_client_role == true
       
  2117 		&& eap.get_type() == m_current_eap_type
       
  2118 		&& m_current_eap_type != eap_type_none)
       
  2119 	{
       
  2120 		/*
       
  2121 		 * Once a peer has sent a Response of the same Type as the initial
       
  2122 		 * Request, an authenticator MUST NOT send a Request of a different Type
       
  2123 		 * prior to completion of the final round of a given method (with the
       
  2124 		 * exception of a Notification-Request) and MUST NOT send a Request for
       
  2125 		 * an additional method of any Type after completion of the initial
       
  2126 		 * authentication method; a peer receiving such Requests MUST treat them
       
  2127 		 * as invalid, and silently discard them. As a result, Identity Requery
       
  2128 		 * is not supported.
       
  2129 		 */
       
  2130 		if (m_eap_type_response_sent == false)
       
  2131 		{
       
  2132 			// Send state change notification
       
  2133 			eap_state_notification_c notification(
       
  2134 				m_am_tools,
       
  2135 				send_network_id,
       
  2136 				m_is_client,
       
  2137 				eap_state_notification_eap,
       
  2138 				eap_protocol_layer_eap,
       
  2139 				m_current_eap_type,
       
  2140 				eap_state_none,
       
  2141 				eap_state_eap_response_sent,
       
  2142 				eap.get_identifier(),
       
  2143 				false);
       
  2144 			state_notification(&notification);
       
  2145 		}
       
  2146 		m_eap_type_response_sent = true;
       
  2147 	}
       
  2148 
       
  2149 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2150 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2151 }
       
  2152 
       
  2153 //--------------------------------------------------
       
  2154 
       
  2155 EAP_FUNC_EXPORT eap_status_e eap_core_c::resend_packet(
       
  2156 	const eap_am_network_id_c * const send_network_id,
       
  2157 	eap_buf_chain_wr_c * const sent_packet,
       
  2158 	const u32_t header_offset,
       
  2159 	const u32_t data_length,
       
  2160 	const u32_t buffer_length,
       
  2161 	const u32_t retransmission_counter)
       
  2162 {
       
  2163 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2164 
       
  2165 	EAP_UNREFERENCED_PARAMETER(retransmission_counter); // Only trace uses this.
       
  2166 
       
  2167 	EAP_TRACE_DEBUG(
       
  2168 		m_am_tools, 
       
  2169 		TRACE_FLAGS_DEFAULT, 
       
  2170 		(EAPL("<- EAP_Core: %s: %s, eap_core_c::resend_packet(), counter %d.\n"),
       
  2171 		 (m_is_client_role == true) ? "client": "server",
       
  2172 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2173 		 retransmission_counter
       
  2174 		 ));
       
  2175 
       
  2176 	// We make a copy because random error test may corrupt the data.
       
  2177 	eap_buf_chain_wr_c * const copy_packet = sent_packet->copy();
       
  2178 
       
  2179 	if (copy_packet == 0)
       
  2180 	{
       
  2181 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2182 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2183 	}
       
  2184 
       
  2185 	EAP_ASSERT(m_eap_header_offset < sent_packet->get_data_length());
       
  2186 	EAP_ASSERT(data_length <= sent_packet->get_data_length());
       
  2187 	EAP_ASSERT(sent_packet->get_data_length() <= buffer_length);
       
  2188 
       
  2189 	// NOTE: send packet directly to partner object.
       
  2190 	// This will skip initialization of re-transmission tfor re-transmitted packet.
       
  2191 	eap_status_e status = m_partner->packet_send(
       
  2192 		send_network_id, 
       
  2193 		copy_packet, 
       
  2194 		header_offset, 
       
  2195 		data_length,
       
  2196 		buffer_length
       
  2197 		);
       
  2198 
       
  2199 	delete copy_packet;
       
  2200 
       
  2201 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2202 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2203 }
       
  2204 
       
  2205 //--------------------------------------------------
       
  2206 
       
  2207 EAP_FUNC_EXPORT eap_status_e eap_core_c::cancel_retransmission()
       
  2208 {
       
  2209 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2210 
       
  2211 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2212 
       
  2213 	//if (m_retransmission != 0)
       
  2214 	{
       
  2215 		EAP_TRACE_DEBUG(
       
  2216 			m_am_tools, 
       
  2217 			TRACE_FLAGS_DEFAULT, 
       
  2218 			(EAPL("TIMER: %s: %s, EAP_CORE_TIMER_RETRANSMISSION_ID cancelled.\n"),
       
  2219 			 (m_is_client_role == true ? "client": "server"),
       
  2220 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2221 			 ));
       
  2222 
       
  2223 		if (m_is_client_role == false)
       
  2224 		{
       
  2225 			// Only EAP-server uses timer to re-transmits EAP-packets.
       
  2226 			m_partner->cancel_timer(this, EAP_CORE_TIMER_RETRANSMISSION_ID);
       
  2227 		}
       
  2228 
       
  2229 		if (m_retransmission != 0)
       
  2230 		{
       
  2231 			delete m_retransmission;
       
  2232 			m_retransmission = 0;
       
  2233 		}
       
  2234 	}
       
  2235 
       
  2236 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2237 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2238 }
       
  2239 
       
  2240 //--------------------------------------------------
       
  2241 
       
  2242 EAP_FUNC_EXPORT eap_status_e eap_core_c::init_retransmission(
       
  2243 	const eap_am_network_id_c * const send_network_id,
       
  2244 	eap_buf_chain_wr_c * const sent_packet,
       
  2245 	const u32_t header_offset,
       
  2246 	const u32_t data_length,
       
  2247 	const eap_code_value_e eap_code,
       
  2248 	const u8_t eap_identifier,
       
  2249 	const eap_type_value_e eap_type
       
  2250 	)
       
  2251 {
       
  2252 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2253 
       
  2254 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2255 
       
  2256 	if (m_is_client_role == false)
       
  2257 	{
       
  2258 		if (m_retransmission_time == 0u
       
  2259 			|| m_retransmission_counter == 0u)
       
  2260 		{
       
  2261 			// No retransmission.
       
  2262 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2263 		}
       
  2264 	}
       
  2265 
       
  2266 	EAP_ASSERT(send_network_id->get_source() != 0);
       
  2267 	EAP_ASSERT(send_network_id->get_destination() != 0);
       
  2268 
       
  2269 	if (m_retransmission != 0)
       
  2270 	{
       
  2271 		delete m_retransmission;
       
  2272 		m_retransmission = 0;
       
  2273 	}
       
  2274 
       
  2275 	m_retransmission = new eap_core_retransmission_c(
       
  2276 		m_am_tools, 
       
  2277 		send_network_id, 
       
  2278 		sent_packet, 
       
  2279 		header_offset, 
       
  2280 		data_length, 
       
  2281 		m_retransmission_time, 
       
  2282 		m_retransmission_counter,
       
  2283 		eap_code,
       
  2284 		eap_identifier,
       
  2285 		eap_type
       
  2286 		);
       
  2287 
       
  2288 	if (m_is_client_role == false)
       
  2289 	{
       
  2290 		// Only EAP-server uses timer to re-transmits EAP-packets.
       
  2291 		m_partner->cancel_timer(this, EAP_CORE_TIMER_RETRANSMISSION_ID);
       
  2292 
       
  2293 		EAP_TRACE_DEBUG(
       
  2294 			m_am_tools, 
       
  2295 			TRACE_FLAGS_DEFAULT, 
       
  2296 			(EAPL("TIMER: %s: %s, EAP_CORE_TIMER_RETRANSMISSION_ID cancelled.\n"),
       
  2297 			 (m_is_client_role == true ? "client": "server"),
       
  2298 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2299 			 ));
       
  2300 	}
       
  2301 
       
  2302 	if (m_retransmission == 0)
       
  2303 	{
       
  2304 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2305 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2306 	}
       
  2307 
       
  2308 	if (m_retransmission->get_is_valid() == true)
       
  2309 	{
       
  2310 		// Because this object do re-transmission other layers must not do re-transmission of this packet.
       
  2311 		sent_packet->set_do_packet_retransmission(false);
       
  2312 
       
  2313 		if (m_is_client_role == false)
       
  2314 		{
       
  2315 			// Only EAP-server uses timer to re-transmits EAP-packets.
       
  2316 			u32_t next_retransmission_time = m_retransmission->get_next_retransmission_time();
       
  2317 
       
  2318 			eap_status_e status = m_partner->set_timer(this, EAP_CORE_TIMER_RETRANSMISSION_ID, 0,
       
  2319 				next_retransmission_time);
       
  2320 			if (status != eap_status_ok)
       
  2321 			{
       
  2322 				delete m_retransmission;
       
  2323 				m_retransmission = 0;
       
  2324 			}
       
  2325 
       
  2326 			EAP_TRACE_DEBUG(
       
  2327 				m_am_tools, 
       
  2328 				TRACE_FLAGS_DEFAULT, 
       
  2329 				(EAPL("TIMER: %s: %s, EAP_CORE_TIMER_RETRANSMISSION_ID set %d ms.\n"),
       
  2330 				 (m_is_client_role == true ? "client": "server"),
       
  2331 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2332 				 next_retransmission_time));
       
  2333 
       
  2334 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2335 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2336 		}
       
  2337 		else
       
  2338 		{
       
  2339 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2340 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2341 		}
       
  2342 	}
       
  2343 	else
       
  2344 	{
       
  2345 		delete m_retransmission;
       
  2346 		m_retransmission = 0;
       
  2347 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2348 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2349 	}
       
  2350 
       
  2351 }
       
  2352 
       
  2353 //--------------------------------------------------
       
  2354 
       
  2355 //
       
  2356 EAP_FUNC_EXPORT eap_status_e eap_core_c::set_eap_failure_timeout()
       
  2357 {
       
  2358 	eap_status_e status = m_partner->set_timer(
       
  2359 		this,
       
  2360 		EAP_CORE_FAILURE_RECEIVED_ID,
       
  2361 		0,
       
  2362 		m_eap_core_failure_received_timeout);
       
  2363 	if (status != eap_status_ok)
       
  2364 	{
       
  2365 		EAP_TRACE_ERROR(
       
  2366 			m_am_tools, 
       
  2367 			TRACE_FLAGS_DEFAULT, 
       
  2368 			(EAPL("ERROR: TIMER: %s: %s, EAP_CORE_FAILURE_RECEIVED_ID failed.\n"),
       
  2369 			 (m_is_client_role == true ? "client": "server"),
       
  2370 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2371 			 ));
       
  2372 
       
  2373 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2374 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2375 	}
       
  2376 	else
       
  2377 	{
       
  2378 		EAP_TRACE_DEBUG(
       
  2379 			m_am_tools, 
       
  2380 			TRACE_FLAGS_DEFAULT, 
       
  2381 			(EAPL("TIMER: %s: %s, EAP_CORE_FAILURE_RECEIVED_ID set %d ms.\n"),
       
  2382 			 (m_is_client_role == true ? "client": "server"),
       
  2383 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2384 			 m_eap_core_failure_received_timeout
       
  2385 			 ));
       
  2386 	}
       
  2387 
       
  2388 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2389 }
       
  2390 
       
  2391 //--------------------------------------------------
       
  2392 
       
  2393 //
       
  2394 EAP_FUNC_EXPORT eap_status_e eap_core_c::cancel_eap_failure_timeout()
       
  2395 {
       
  2396 	EAP_TRACE_DEBUG(
       
  2397 		m_am_tools, 
       
  2398 		TRACE_FLAGS_DEFAULT, 
       
  2399 		(EAPL("TIMER: %s: %s, EAP_CORE_FAILURE_RECEIVED_ID cancelled.\n"),
       
  2400 		 (m_is_client_role == true ? "client": "server"),
       
  2401 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2402 		 ));
       
  2403 
       
  2404 	return m_partner->cancel_timer(
       
  2405 		this,
       
  2406 		EAP_CORE_FAILURE_RECEIVED_ID);
       
  2407 }
       
  2408 
       
  2409 //--------------------------------------------------
       
  2410 
       
  2411 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  2412 
       
  2413 //
       
  2414 eap_status_e eap_core_c::set_wait_eap_request_type_timeout()
       
  2415 {
       
  2416 	EAP_ASSERT_TOOLS(m_am_tools, (m_wait_eap_request_type_timeout_set == false));
       
  2417 
       
  2418 	eap_status_e status = m_partner->set_timer(
       
  2419 		this,
       
  2420 		EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID,
       
  2421 		0,
       
  2422 		m_wait_eap_request_type_timeout);
       
  2423 	if (status != eap_status_ok)
       
  2424 	{
       
  2425 		EAP_TRACE_ERROR(
       
  2426 			m_am_tools, 
       
  2427 			TRACE_FLAGS_DEFAULT, 
       
  2428 			(EAPL("ERROR: TIMER: %s: %s, EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID failed.\n"),
       
  2429 			 (m_is_client_role == true ? "client": "server"),
       
  2430 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2431 			 ));
       
  2432 
       
  2433 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2434 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2435 	}
       
  2436 	else
       
  2437 	{
       
  2438 		EAP_TRACE_DEBUG(
       
  2439 			m_am_tools, 
       
  2440 			TRACE_FLAGS_DEFAULT, 
       
  2441 			(EAPL("TIMER: %s: %s, EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID set %d ms.\n"),
       
  2442 			 (m_is_client_role == true ? "client": "server"),
       
  2443 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2444 			 m_wait_eap_request_type_timeout
       
  2445 			 ));
       
  2446 
       
  2447 		m_wait_eap_request_type_timeout_set = true;
       
  2448 	}
       
  2449 
       
  2450 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2451 }
       
  2452 
       
  2453 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  2454 
       
  2455 //--------------------------------------------------
       
  2456 
       
  2457 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  2458 
       
  2459 //
       
  2460 eap_status_e eap_core_c::cancel_wait_eap_request_type_timeout()
       
  2461 {
       
  2462 	if (m_wait_eap_request_type_timeout_set == true)
       
  2463 	{
       
  2464 		EAP_TRACE_DEBUG(
       
  2465 			m_am_tools, 
       
  2466 			TRACE_FLAGS_DEFAULT, 
       
  2467 			(EAPL("TIMER: %s: %s, EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID cancelled.\n"),
       
  2468 			 (m_is_client_role == true ? "client": "server"),
       
  2469 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  2470 			 ));
       
  2471 
       
  2472 		m_wait_eap_request_type_timeout_set = false;
       
  2473 
       
  2474 		return m_partner->cancel_timer(
       
  2475 			this,
       
  2476 			EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID);
       
  2477 	}
       
  2478 	else
       
  2479 	{
       
  2480 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2481 	}
       
  2482 }
       
  2483 
       
  2484 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  2485 
       
  2486 //--------------------------------------------------
       
  2487 
       
  2488 //
       
  2489 EAP_FUNC_EXPORT u32_t eap_core_c::get_header_offset(
       
  2490 	u32_t * const MTU,
       
  2491 	u32_t * const trailer_length)
       
  2492 {
       
  2493 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2494 
       
  2495 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2496 
       
  2497 	const u32_t offset = m_partner->get_header_offset(MTU, trailer_length);
       
  2498 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2499 
       
  2500 	EAP_TRACE_DEBUG(
       
  2501 		m_am_tools,
       
  2502 		TRACE_FLAGS_DEFAULT,
       
  2503 		(EAPL("eap_core_c::get_header_offset(): offset=%d, MTU=%d, trailer_length=%d\n"),
       
  2504 		offset,
       
  2505 		*MTU,
       
  2506 		*trailer_length));
       
  2507 
       
  2508 	return offset;
       
  2509 }
       
  2510 
       
  2511 //--------------------------------------------------
       
  2512 
       
  2513 //
       
  2514 EAP_FUNC_EXPORT eap_status_e eap_core_c::load_module(
       
  2515 	const eap_type_value_e type,
       
  2516 	const eap_type_value_e tunneling_type,
       
  2517 	abs_eap_base_type_c * const partner,
       
  2518 	eap_base_type_c ** const handler,
       
  2519 	const bool is_client_when_true,
       
  2520 	const eap_am_network_id_c * const receive_network_id)
       
  2521 {
       
  2522 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2523 
       
  2524 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2525 
       
  2526 	const eap_status_e status = m_partner->load_module(
       
  2527 		type,
       
  2528 		tunneling_type,
       
  2529 		partner,
       
  2530 		handler,
       
  2531 		is_client_when_true,
       
  2532 		receive_network_id);
       
  2533 
       
  2534 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2535 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2536 }
       
  2537 
       
  2538 //--------------------------------------------------
       
  2539 
       
  2540 //
       
  2541 EAP_FUNC_EXPORT eap_status_e eap_core_c::configure()
       
  2542 {
       
  2543 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2544 
       
  2545 #if !defined(USE_EAP_DEBUG_TRACE)
       
  2546 	EAP_TRACE_ALWAYS(
       
  2547 		m_am_tools, 
       
  2548 		TRACE_FLAGS_DEFAULT, 
       
  2549 		(EAPL("eap_core_c::configure(): %s: %s.\n"),
       
  2550 		 ((m_is_client == true) ? "client": "server"),
       
  2551 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"));
       
  2552 #else
       
  2553 	EAP_TRACE_ALWAYS(
       
  2554 		m_am_tools, 
       
  2555 		TRACE_FLAGS_DEFAULT, 
       
  2556 		(EAPL("eap_core_c::configure(): %s: %s, this = 0x%08x => 0x%08x.\n"),
       
  2557 		 ((m_is_client == true) ? "client": "server"),
       
  2558 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2559 		 this,
       
  2560 		 dynamic_cast<abs_eap_base_timer_c *>(this)));
       
  2561 #endif
       
  2562 
       
  2563 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_core_c::configure()");
       
  2564 
       
  2565 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2566 
       
  2567 	eap_status_e status(eap_status_process_general_error);
       
  2568 
       
  2569 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  2570 
       
  2571 	{
       
  2572 		eap_variable_data_c data(m_am_tools);
       
  2573 
       
  2574 		status = m_partner->read_configure(
       
  2575 			cf_str_EAP_default_type_hex_data.get_field(),
       
  2576 			&data);
       
  2577 		if (status == eap_status_illegal_configure_type)
       
  2578 		{
       
  2579 			status = m_partner->read_configure(
       
  2580 				cf_str_EAP_default_type_u32_t.get_field(),
       
  2581 				&data);
       
  2582 		}
       
  2583 
       
  2584 #if defined(USE_EAP_CORE_SERVER)
       
  2585 		if (m_is_client == false)
       
  2586 		{
       
  2587 			// This option is only applicable in server.
       
  2588 
       
  2589 			eap_variable_data_c server_data(m_am_tools);
       
  2590 
       
  2591 			eap_status_e server_status = m_partner->read_configure(
       
  2592 				cf_str_EAP_server_default_type_hex_data.get_field(),
       
  2593 				&server_data);
       
  2594 			if (server_status == eap_status_illegal_configure_type)
       
  2595 			{
       
  2596 				server_status = m_partner->read_configure(
       
  2597 					cf_str_EAP_server_default_type_u32_t.get_field(),
       
  2598 					&server_data);
       
  2599 			}
       
  2600 
       
  2601 			if (server_status == eap_status_ok
       
  2602 				&& server_data.get_is_valid_data() == true)
       
  2603 			{
       
  2604 				status = data.set_copy_of_buffer(&server_data);
       
  2605 			}
       
  2606 		}
       
  2607 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  2608 
       
  2609 		if (status != eap_status_ok)
       
  2610 		{
       
  2611 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2612 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2613 		}
       
  2614 		else if (data.get_data_length() == sizeof(u32_t)
       
  2615 			&& data.get_data(data.get_data_length()) != 0)
       
  2616 		{
       
  2617 			m_default_eap_type
       
  2618 				= *(reinterpret_cast<eap_type_ietf_values_e *>(
       
  2619 						data.get_data(data.get_data_length())));
       
  2620 		}
       
  2621 		else if (data.get_data_length() == eap_expanded_type_c::get_eap_expanded_type_size()
       
  2622 			&& data.get_data(data.get_data_length()) != 0)
       
  2623 		{
       
  2624 			eap_expanded_type_c eap_type(eap_type_none);
       
  2625 
       
  2626 			status = eap_type.set_expanded_type_data(
       
  2627 				m_am_tools,
       
  2628 				&data);
       
  2629 			if (status != eap_status_ok)
       
  2630 			{
       
  2631 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2632 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2633 			}
       
  2634 
       
  2635 			status = eap_type.get_type_data(
       
  2636 				m_am_tools,
       
  2637 				&m_default_eap_type);
       
  2638 			if (status != eap_status_ok)
       
  2639 			{
       
  2640 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2641 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2642 			}
       
  2643 		}
       
  2644 		else
       
  2645 		{
       
  2646 			EAP_TRACE_DEBUG(
       
  2647 				m_am_tools, 
       
  2648 				TRACE_FLAGS_DEFAULT, 
       
  2649 				(EAPL("ERROR: %s: %s, No EAP-type configured, %s.\n"),
       
  2650 				 (m_is_client == true ? "client": "server"),
       
  2651 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  2652 				 cf_str_EAP_default_type_hex_data.get_field()->get_field()));
       
  2653 			
       
  2654 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2655 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  2656 		}
       
  2657 	}
       
  2658 
       
  2659 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  2660 
       
  2661 #if defined(USE_EAP_TEST_VECTORS)
       
  2662 
       
  2663 	{
       
  2664 		eap_variable_data_c data(m_am_tools);
       
  2665 
       
  2666 		status = m_partner->read_configure(
       
  2667 			cf_str_EAP_TRACE_only_trace_messages.get_field(),
       
  2668 			&data);
       
  2669 		if (status == eap_status_ok
       
  2670 			&& data.get_data_length() == sizeof(u32_t)
       
  2671 			&& data.get_data(data.get_data_length()) != 0)
       
  2672 		{
       
  2673 			if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
       
  2674 			{
       
  2675 				// Activate only EAP message traces.
       
  2676 				m_am_tools->set_trace_mask(
       
  2677 					eap_am_tools_c::eap_trace_mask_always
       
  2678 					| eap_am_tools_c::eap_trace_mask_eap_messages);
       
  2679 			}
       
  2680 			else
       
  2681 			{
       
  2682 				// Disable only EAP message traces.
       
  2683 				m_am_tools->set_trace_mask(
       
  2684 					m_am_tools->get_trace_mask() & (~eap_am_tools_c::eap_trace_mask_eap_messages));
       
  2685 			}
       
  2686 		}
       
  2687 		else
       
  2688 		{
       
  2689 			// Disable only EAP message traces.
       
  2690 			m_am_tools->set_trace_mask(
       
  2691 				m_am_tools->get_trace_mask() & (~eap_am_tools_c::eap_trace_mask_eap_messages));
       
  2692 		}
       
  2693 	}
       
  2694 
       
  2695 
       
  2696 	{
       
  2697 		eap_variable_data_c data(m_am_tools);
       
  2698 
       
  2699 		status = m_partner->read_configure(
       
  2700 			cf_str_EAP_TRACE_only_test_vectors.get_field(),
       
  2701 			&data);
       
  2702 		if (status == eap_status_ok
       
  2703 			&& data.get_data_length() == sizeof(u32_t)
       
  2704 			&& data.get_data(data.get_data_length()) != 0)
       
  2705 		{
       
  2706 			if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
       
  2707 			{
       
  2708 				// Activates only EAP test vector traces.
       
  2709 				m_am_tools->set_trace_mask(eap_am_tools_c::eap_trace_mask_test_vectors);
       
  2710 			}
       
  2711 		}
       
  2712 	}
       
  2713 
       
  2714 
       
  2715 	{
       
  2716 		eap_variable_data_c data(m_am_tools);
       
  2717 
       
  2718 		status = m_partner->read_configure(
       
  2719 			cf_str_EAP_TRACE_crypto_test_vectors_sha1.get_field(),
       
  2720 			&data);
       
  2721 		if (status == eap_status_ok
       
  2722 			&& data.get_data_length() == sizeof(u32_t)
       
  2723 			&& data.get_data(data.get_data_length()) != 0)
       
  2724 		{
       
  2725 			if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
       
  2726 			{
       
  2727 				// Activates SHA1 EAP test vector traces.
       
  2728 				m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
       
  2729 					| eap_am_tools_c::eap_trace_mask_crypto_sha1);
       
  2730 			}
       
  2731 		}
       
  2732 	}
       
  2733 
       
  2734 
       
  2735 	{
       
  2736 		eap_variable_data_c data(m_am_tools);
       
  2737 
       
  2738 		status = m_partner->read_configure(
       
  2739 			cf_str_EAP_TRACE_crypto_test_vectors_rc4.get_field(),
       
  2740 			&data);
       
  2741 		if (status == eap_status_ok
       
  2742 			&& data.get_data_length() == sizeof(u32_t)
       
  2743 			&& data.get_data(data.get_data_length()) != 0)
       
  2744 		{
       
  2745 			if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
       
  2746 			{
       
  2747 				// Activates RC4 EAP test vector traces.
       
  2748 				m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
       
  2749 					| eap_am_tools_c::eap_trace_mask_crypto_rc4);
       
  2750 			}
       
  2751 		}
       
  2752 	}
       
  2753 
       
  2754 
       
  2755 	{
       
  2756 		eap_variable_data_c data(m_am_tools);
       
  2757 
       
  2758 		status = m_partner->read_configure(
       
  2759 			cf_str_EAP_TRACE_crypto_test_vectors_md4.get_field(),
       
  2760 			&data);
       
  2761 		if (status == eap_status_ok
       
  2762 			&& data.get_data_length() == sizeof(u32_t)
       
  2763 			&& data.get_data(data.get_data_length()) != 0)
       
  2764 		{
       
  2765 			if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
       
  2766 			{
       
  2767 				// Activates MD4 EAP test vector traces.
       
  2768 				m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
       
  2769 					| eap_am_tools_c::eap_trace_mask_crypto_md4);
       
  2770 			}
       
  2771 		}
       
  2772 	}
       
  2773 
       
  2774 
       
  2775 	{
       
  2776 		eap_variable_data_c data(m_am_tools);
       
  2777 
       
  2778 		status = m_partner->read_configure(
       
  2779 			cf_str_EAP_TRACE_crypto_test_vectors_test_random.get_field(),
       
  2780 			&data);
       
  2781 		if (status == eap_status_ok
       
  2782 			&& data.get_data_length() == sizeof(u32_t)
       
  2783 			&& data.get_data(data.get_data_length()) != 0)
       
  2784 		{
       
  2785 			if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
       
  2786 			{
       
  2787 				// Activates test random generator EAP test vector traces.
       
  2788 				m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
       
  2789 					| eap_am_tools_c::eap_trace_mask_crypto_test_random
       
  2790 					| eap_am_tools_c::eap_trace_mask_crypto_sha1);
       
  2791 			}
       
  2792 		}
       
  2793 	}
       
  2794 
       
  2795 #endif //#if defined(USE_EAP_TEST_VECTORS)
       
  2796 
       
  2797 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  2798 
       
  2799 #if defined(USE_EAP_CORE_SERVER)
       
  2800 	if (m_is_client == false)
       
  2801 	{
       
  2802 		eap_variable_data_c data(m_am_tools);
       
  2803 
       
  2804 		status = m_partner->read_configure(
       
  2805 			cf_str_EAP_CORE_process_EAP_Nak_immediately.get_field(),
       
  2806 			&data);
       
  2807 		if (status == eap_status_ok
       
  2808 			&& data.get_data_length() == sizeof(u32_t)
       
  2809 			&& data.get_data(data.get_data_length()) != 0)
       
  2810 		{
       
  2811 			u32_t *flag = reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()));
       
  2812 
       
  2813 			if (flag != 0)
       
  2814 			{
       
  2815 				if ((*flag) != 0ul)
       
  2816 				{
       
  2817 					m_process_eap_nak_immediately = true;
       
  2818 				}
       
  2819 				else
       
  2820 				{
       
  2821 					m_process_eap_nak_immediately = false;
       
  2822 				}
       
  2823 			}
       
  2824 		}
       
  2825 	}
       
  2826 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  2827 
       
  2828 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  2829 
       
  2830 #if defined(USE_EAP_CORE_SERVER)
       
  2831 	if (m_is_client == false)
       
  2832 	{
       
  2833 		eap_variable_data_c retransmission_time(m_am_tools);
       
  2834 
       
  2835 		status = read_configure(
       
  2836 			cf_str_EAP_CORE_retransmission_time.get_field(),
       
  2837 			&retransmission_time);
       
  2838 		if (status == eap_status_ok
       
  2839 			&& retransmission_time.get_is_valid_data() == true)
       
  2840 		{
       
  2841 			u32_t *retransmission_time_value = reinterpret_cast<u32_t *>(
       
  2842 				retransmission_time.get_data(sizeof(u32_t)));
       
  2843 			if (retransmission_time_value != 0)
       
  2844 			{
       
  2845 				m_retransmission_time = *retransmission_time_value;
       
  2846 			}
       
  2847 			else
       
  2848 			{
       
  2849 				m_retransmission_time = EAP_CORE_RETRANSMISSION_TIME;
       
  2850 			}
       
  2851 		}
       
  2852 		else
       
  2853 		{
       
  2854 			m_retransmission_time = EAP_CORE_RETRANSMISSION_TIME;
       
  2855 		}
       
  2856 	}
       
  2857 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  2858 
       
  2859 	//if (m_is_client == false)
       
  2860 	{
       
  2861 		eap_variable_data_c retransmission_counter(m_am_tools);
       
  2862 
       
  2863 		status = read_configure(
       
  2864 			cf_str_EAP_CORE_retransmission_counter.get_field(),
       
  2865 			&retransmission_counter);
       
  2866 		if (status == eap_status_ok
       
  2867 			&& retransmission_counter.get_is_valid_data() == true)
       
  2868 		{
       
  2869 			u32_t *retransmission_counter_value = reinterpret_cast<u32_t *>(
       
  2870 				retransmission_counter.get_data(sizeof(u32_t)));
       
  2871 			if (retransmission_counter_value != 0)
       
  2872 			{
       
  2873 				m_retransmission_counter = *retransmission_counter_value;
       
  2874 			}
       
  2875 			else
       
  2876 			{
       
  2877 				m_retransmission_counter = EAP_CORE_RETRANSMISSION_COUNTER;
       
  2878 			}
       
  2879 		}
       
  2880 		else
       
  2881 		{
       
  2882 			m_retransmission_counter = EAP_CORE_RETRANSMISSION_COUNTER;
       
  2883 		}
       
  2884 	}
       
  2885 
       
  2886 	//----------------------------------------------------------
       
  2887 
       
  2888 	{
       
  2889 		eap_variable_data_c session_timeout(m_am_tools);
       
  2890 
       
  2891 		status = read_configure(
       
  2892 			cf_str_EAP_CORE_session_timeout.get_field(),
       
  2893 			&session_timeout);
       
  2894 		if (status == eap_status_ok
       
  2895 			&& session_timeout.get_is_valid_data() == true)
       
  2896 		{
       
  2897 			u32_t *handler_timeout = reinterpret_cast<u32_t *>(
       
  2898 				session_timeout.get_data(sizeof(u32_t)));
       
  2899 			if (handler_timeout != 0)
       
  2900 			{
       
  2901 				m_session_timeout = *handler_timeout;
       
  2902 			}
       
  2903 			else
       
  2904 			{
       
  2905 				m_session_timeout = EAP_CORE_SESSION_TIMEOUT;
       
  2906 			}
       
  2907 		}
       
  2908 		else
       
  2909 		{
       
  2910 			m_session_timeout = EAP_CORE_SESSION_TIMEOUT;
       
  2911 		}
       
  2912 	}
       
  2913 
       
  2914 
       
  2915 #if defined(USE_EAP_CORE_SERVER)
       
  2916 
       
  2917 	if (m_is_client == false)
       
  2918 	{
       
  2919 		eap_variable_data_c session_timeout(m_am_tools);
       
  2920 
       
  2921 		status = read_configure(
       
  2922 			cf_str_EAP_CORE_server_session_timeout.get_field(),
       
  2923 			&session_timeout);
       
  2924 		if (status == eap_status_ok
       
  2925 			&& session_timeout.get_is_valid_data() == true)
       
  2926 		{
       
  2927 			u32_t *handler_timeout = reinterpret_cast<u32_t *>(
       
  2928 				session_timeout.get_data(sizeof(u32_t)));
       
  2929 			if (handler_timeout != 0)
       
  2930 			{
       
  2931 				// This is optional.
       
  2932 				m_session_timeout = *handler_timeout;
       
  2933 			}
       
  2934 		}
       
  2935 	}
       
  2936 
       
  2937 	if (m_is_client == false)
       
  2938 	{
       
  2939 		eap_variable_data_c data(m_am_tools);
       
  2940 
       
  2941 		status = m_partner->read_configure(
       
  2942 			cf_str_EAP_CORE_send_eap_success_after_notification.get_field(),
       
  2943 			&data);
       
  2944 		if (status == eap_status_ok
       
  2945 			&& data.get_data_length() == sizeof(u32_t)
       
  2946 			&& data.get_data(data.get_data_length()) != 0)
       
  2947 		{
       
  2948 			u32_t *flag = reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()));
       
  2949 
       
  2950 			if (flag != 0)
       
  2951 			{
       
  2952 				if ((*flag) != 0ul)
       
  2953 				{
       
  2954 					m_send_eap_success_after_notification = true;
       
  2955 				}
       
  2956 				else
       
  2957 				{
       
  2958 					m_send_eap_success_after_notification = false;
       
  2959 				}
       
  2960 			}
       
  2961 		}
       
  2962 	}
       
  2963 
       
  2964 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  2965 
       
  2966 	//----------------------------------------------------------
       
  2967 
       
  2968 	{
       
  2969 		eap_variable_data_c failure_received_timeout(m_am_tools);
       
  2970 
       
  2971 		status = read_configure(
       
  2972 			cf_str_EAP_CORE_failure_received_timeout.get_field(),
       
  2973 			&failure_received_timeout);
       
  2974 		if (status == eap_status_ok
       
  2975 			&& failure_received_timeout.get_is_valid_data() == true)
       
  2976 		{
       
  2977 			u32_t *timeout = reinterpret_cast<u32_t *>(
       
  2978 				failure_received_timeout.get_data(sizeof(u32_t)));
       
  2979 			if (timeout != 0)
       
  2980 			{
       
  2981 				m_eap_core_failure_received_timeout = *timeout;
       
  2982 			}
       
  2983 		}
       
  2984 	}
       
  2985 
       
  2986 	//----------------------------------------------------------
       
  2987 
       
  2988 	if (m_is_tunneled_eap == false)
       
  2989 	{
       
  2990 		eap_variable_data_c remove_session_timeout(m_am_tools);
       
  2991 
       
  2992 		status = read_configure(
       
  2993 			cf_str_EAP_CORE_remove_session_timeout.get_field(),
       
  2994 			&remove_session_timeout);
       
  2995 		if (status == eap_status_ok
       
  2996 			&& remove_session_timeout.get_is_valid_data() == true)
       
  2997 		{
       
  2998 			u32_t *remove_session_timeout_value = reinterpret_cast<u32_t *>(
       
  2999 				remove_session_timeout.get_data(sizeof(u32_t)));
       
  3000 			if (remove_session_timeout_value != 0)
       
  3001 			{
       
  3002 				m_remove_session_timeout = *remove_session_timeout_value;
       
  3003 			}
       
  3004 		}
       
  3005 	}
       
  3006 	else
       
  3007 	{
       
  3008 		// Inside the tunnel we do not need any timeout.
       
  3009 		m_remove_session_timeout = 0ul;
       
  3010 	}
       
  3011 
       
  3012 	//----------------------------------------------------------
       
  3013 
       
  3014 #if defined(USE_EAP_EXPANDED_TYPES)
       
  3015 	{
       
  3016 		eap_variable_data_c use_eap_expanded_type(m_am_tools);
       
  3017 
       
  3018 		status = m_partner->read_configure(
       
  3019 			cf_str_EAP_CORE_use_eap_expanded_type.get_field(),
       
  3020 			&use_eap_expanded_type);
       
  3021 		if (status == eap_status_ok
       
  3022 			&& use_eap_expanded_type.get_data_length() == sizeof(u32_t)
       
  3023 			&& use_eap_expanded_type.get_data() != 0)
       
  3024 		{
       
  3025 			u32_t *flag = reinterpret_cast<u32_t *>(use_eap_expanded_type.get_data(use_eap_expanded_type.get_data_length()));
       
  3026 
       
  3027 			if (flag != 0)
       
  3028 			{
       
  3029 				if ((*flag) != 0ul)
       
  3030 				{
       
  3031 					m_use_eap_expanded_type = true;
       
  3032 				}
       
  3033 				else
       
  3034 				{
       
  3035 					m_use_eap_expanded_type = false;
       
  3036 				}
       
  3037 			}
       
  3038 		}
       
  3039 	}
       
  3040 #endif //#if defined(USE_EAP_EXPANDED_TYPES)
       
  3041 
       
  3042 	//----------------------------------------------------------
       
  3043 
       
  3044 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3045 	{
       
  3046 		eap_variable_data_c wait_eap_request_type_timeout(m_am_tools);
       
  3047 
       
  3048 		status = read_configure(
       
  3049 			cf_str_EAP_CORE_wait_eap_request_type_timeout.get_field(),
       
  3050 			&wait_eap_request_type_timeout);
       
  3051 		if (status == eap_status_ok
       
  3052 			&& wait_eap_request_type_timeout.get_is_valid_data() == true)
       
  3053 		{
       
  3054 			u32_t *timeout = reinterpret_cast<u32_t *>(
       
  3055 				wait_eap_request_type_timeout.get_data(sizeof(u32_t)));
       
  3056 			if (timeout != 0)
       
  3057 			{
       
  3058 				m_wait_eap_request_type_timeout = *timeout;
       
  3059 			}
       
  3060 		}
       
  3061 	}
       
  3062 
       
  3063 #if defined(USE_EAP_CORE_SERVER)
       
  3064 	if (m_is_tunneled_eap == false)
       
  3065 	{
       
  3066 		
       
  3067 		eap_variable_data_c skip_eap_request_identity(m_am_tools);
       
  3068 
       
  3069 		status = m_partner->read_configure(
       
  3070 			cf_str_EAP_CORE_skip_eap_request_identity.get_field(),
       
  3071 			&skip_eap_request_identity);
       
  3072 		if (status == eap_status_ok
       
  3073 			&& skip_eap_request_identity.get_data_length() == sizeof(u32_t)
       
  3074 			&& skip_eap_request_identity.get_data() != 0)
       
  3075 		{
       
  3076 			u32_t *flag = reinterpret_cast<u32_t *>(skip_eap_request_identity.get_data(skip_eap_request_identity.get_data_length()));
       
  3077 
       
  3078 			if (flag != 0)
       
  3079 			{
       
  3080 				if ((*flag) != 0ul)
       
  3081 				{
       
  3082 					m_skip_eap_request_identity = true;
       
  3083 				}
       
  3084 				else
       
  3085 				{
       
  3086 					m_skip_eap_request_identity = false;
       
  3087 				}
       
  3088 			}
       
  3089 		}
       
  3090 	}
       
  3091 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  3092 
       
  3093 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3094 
       
  3095 	//----------------------------------------------------------
       
  3096 
       
  3097 	m_eap_header_offset = m_partner->get_header_offset(&m_MTU, &m_trailer_length);
       
  3098 
       
  3099 
       
  3100 	// Add session timeout.
       
  3101 	status = initialize_session_timeout(m_session_timeout);
       
  3102 	if (status != eap_status_ok)
       
  3103 	{
       
  3104 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3105 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3106 	}
       
  3107 
       
  3108 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3109 
       
  3110 	if (m_is_tunneled_eap == false
       
  3111 		&& m_is_client_role == true)
       
  3112 	{
       
  3113 		status = cancel_wait_eap_request_type_timeout();
       
  3114 		if (status != eap_status_ok)
       
  3115 		{
       
  3116 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3117 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3118 		}
       
  3119 
       
  3120 		status = set_wait_eap_request_type_timeout();
       
  3121 	}
       
  3122 
       
  3123 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3124 
       
  3125 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3126 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3127 }
       
  3128 
       
  3129 //--------------------------------------------------
       
  3130 
       
  3131 //
       
  3132 EAP_FUNC_EXPORT eap_status_e eap_core_c::shutdown_operation(
       
  3133 	eap_base_type_c * const handler,
       
  3134 	abs_eap_am_tools_c * const m_am_tools)
       
  3135 {
       
  3136 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3137 
       
  3138 	EAP_UNREFERENCED_PARAMETER(m_am_tools);
       
  3139 
       
  3140 	EAP_TRACE_ALWAYS(
       
  3141 		m_am_tools, 
       
  3142 		TRACE_FLAGS_DEFAULT, 
       
  3143 		(EAPL("eap_core_c::shutdown_operation(): handler=0x%08x.\n"),
       
  3144 		 handler));
       
  3145 
       
  3146 	eap_status_e status = handler->shutdown();
       
  3147 
       
  3148 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3149 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3150 }
       
  3151 
       
  3152 //--------------------------------------------------
       
  3153 
       
  3154 //
       
  3155 EAP_FUNC_EXPORT eap_status_e eap_core_c::shutdown()
       
  3156 {
       
  3157 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3158 	
       
  3159 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3160 
       
  3161 #if !defined(USE_EAP_DEBUG_TRACE)
       
  3162 	EAP_TRACE_ALWAYS(
       
  3163 		m_am_tools, 
       
  3164 		TRACE_FLAGS_DEFAULT, 
       
  3165 		(EAPL("eap_core_c::shutdown(): %s: %s, m_shutdown_was_called=%d.\n"),
       
  3166 		 ((m_is_client == true) ? "client": "server"),
       
  3167 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3168 		 m_shutdown_was_called));
       
  3169 #else
       
  3170 	EAP_TRACE_ALWAYS(
       
  3171 		m_am_tools, 
       
  3172 		TRACE_FLAGS_DEFAULT, 
       
  3173 		(EAPL("eap_core_c::shutdown(): %s: %s, this = 0x%08x => 0x%08x, ")
       
  3174 		 EAPL("m_shutdown_was_called=%d.\n"),
       
  3175 		 ((m_is_client == true) ? "client": "server"),
       
  3176 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3177 		 this,
       
  3178 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
  3179 		 m_shutdown_was_called));
       
  3180 #endif
       
  3181 
       
  3182 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_core_c::shutdown()");
       
  3183 
       
  3184 	if (m_shutdown_was_called == true)
       
  3185 	{
       
  3186 		// Shutdown was already called once.
       
  3187 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3188 	}
       
  3189 	m_shutdown_was_called = true;
       
  3190 
       
  3191 	if (m_partner == 0)
       
  3192 	{
       
  3193 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  3194 	}
       
  3195 
       
  3196 	EAP_TRACE_DEBUG(
       
  3197 		m_am_tools,
       
  3198 		TRACE_FLAGS_DEFAULT,
       
  3199 		(EAPL("eap_core_c::shutdown(): m_is_tunneled_eap=%d, m_eap_type_response_sent=%d\n"),
       
  3200 		m_is_tunneled_eap,
       
  3201 		m_eap_type_response_sent));
       
  3202 
       
  3203 	if (m_is_client == true
       
  3204 		&& m_is_tunneled_eap == false
       
  3205 		&& m_eap_type_response_sent == false)
       
  3206 	{
       
  3207 		// EAP-authentication failed before any EAP-messages.
       
  3208 
       
  3209 		EAP_TRACE_DEBUG(
       
  3210 			m_am_tools,
       
  3211 			TRACE_FLAGS_DEFAULT,
       
  3212 			(EAPL("eap_core_c::shutdown(): EAP-authentication failed before any EAP-messages.\n")));
       
  3213 
       
  3214 		eap_am_network_id_c send_network_id(m_am_tools,
       
  3215 			m_receive_network_id.get_destination_id(),
       
  3216 			m_receive_network_id.get_source_id(),
       
  3217 			m_receive_network_id.get_type());
       
  3218 
       
  3219 		eap_state_notification_c notification(
       
  3220 			m_am_tools,
       
  3221 			&send_network_id,
       
  3222 			m_is_client,
       
  3223 			eap_state_notification_eap,
       
  3224 			eap_protocol_layer_eap,
       
  3225 			m_current_eap_type,
       
  3226 			eap_state_none,
       
  3227 			eap_state_authentication_terminated_unsuccessfully,
       
  3228 			m_eap_identity_request_identifier_client,
       
  3229 			false);
       
  3230 
       
  3231 		notification.set_authentication_error(eap_status_authentication_failure);
       
  3232 
       
  3233 		state_notification(&notification);
       
  3234 	}
       
  3235 
       
  3236 	eap_status_e status = m_type_map.for_each(shutdown_operation, true);
       
  3237 
       
  3238 
       
  3239 	cancel_retransmission();
       
  3240 
       
  3241 	cancel_session_timeout();
       
  3242 
       
  3243 	cancel_eap_failure_timeout();
       
  3244 
       
  3245 	cancel_asynchronous_init_remove_eap_session();
       
  3246 
       
  3247 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3248 	if (m_is_tunneled_eap == false
       
  3249 		&& m_is_client_role == true)
       
  3250 	{
       
  3251 		cancel_wait_eap_request_type_timeout();
       
  3252 	}
       
  3253 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3254 
       
  3255 
       
  3256 	if (m_partner != 0)
       
  3257 	{
       
  3258 
       
  3259 #if defined(USE_EAP_CORE_SERVER)
       
  3260 		m_partner->cancel_timer(this, EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID);
       
  3261 
       
  3262 		EAP_TRACE_DEBUG(
       
  3263 			m_am_tools, 
       
  3264 			TRACE_FLAGS_DEFAULT, 
       
  3265 			(EAPL("TIMER: %s: %s, EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID ")
       
  3266 			 EAPL("cancelled, this = 0x%08x.\n"),
       
  3267 			 (m_is_client == true ? "client": "server"),
       
  3268 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3269 			 this));
       
  3270 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  3271 
       
  3272 		m_partner->cancel_timer(this, EAP_CORE_SESSION_TIMEOUT_ID);
       
  3273 
       
  3274 		EAP_TRACE_DEBUG(
       
  3275 			m_am_tools, 
       
  3276 			TRACE_FLAGS_DEFAULT, 
       
  3277 			(EAPL("TIMER: %s: %s, EAP_CORE_SESSION_TIMEOUT_ID cancelled, this = 0x%08x.\n"),
       
  3278 			 (m_is_client == true ? "client": "server"),
       
  3279 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3280 			 this));
       
  3281 	}
       
  3282 
       
  3283 #if !defined(USE_EAP_DEBUG_TRACE)
       
  3284 	EAP_TRACE_ALWAYS(
       
  3285 		m_am_tools, 
       
  3286 		TRACE_FLAGS_DEFAULT, 
       
  3287 		(EAPL("eap_core_c::shutdown(): %s: %s, m_shutdown_was_called=%d, status=%d returns.\n"),
       
  3288 		 ((m_is_client == true) ? "client": "server"),
       
  3289 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3290 		 m_shutdown_was_called,
       
  3291 		 status));
       
  3292 #else
       
  3293 	EAP_TRACE_ALWAYS(
       
  3294 		m_am_tools, 
       
  3295 		TRACE_FLAGS_DEFAULT, 
       
  3296 		(EAPL("eap_core_c::shutdown(): %s: %s, this = 0x%08x => 0x%08x, ")
       
  3297 		 EAPL("m_shutdown_was_called=%d, status=%d returns.\n"),
       
  3298 		 ((m_is_client == true) ? "client": "server"),
       
  3299 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3300 		 this,
       
  3301 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
  3302 		 m_shutdown_was_called,
       
  3303 		 status));
       
  3304 #endif
       
  3305 
       
  3306 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3307 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3308 }
       
  3309 
       
  3310 //--------------------------------------------------
       
  3311 
       
  3312 //
       
  3313 EAP_FUNC_EXPORT eap_status_e eap_core_c::unload_module(const eap_type_value_e type)
       
  3314 {
       
  3315 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3316 
       
  3317 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3318 
       
  3319 	const eap_status_e status = m_partner->unload_module(type);
       
  3320 
       
  3321 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3322 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3323 }
       
  3324 
       
  3325 //--------------------------------------------------
       
  3326 
       
  3327 EAP_FUNC_EXPORT eap_status_e eap_core_c::eap_acknowledge(
       
  3328 	const eap_am_network_id_c * const receive_network_id)
       
  3329 {
       
  3330 	// Any Network Protocol packet is accepted as a success indication.
       
  3331 	// This is described in RFC 2284 "PPP Extensible Authentication Protocol (EAP)".
       
  3332 
       
  3333 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3334 
       
  3335 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3336 
       
  3337 	eap_status_e status(eap_status_process_general_error);
       
  3338 
       
  3339 	/**
       
  3340 	 * @{ 2003-10-01 draft-ietf-eap-rfc2284bis-06.txt chapter 3.4 Lower layer indications:
       
  3341 	 * To improve reliability, if a peer receives a lower layer success
       
  3342 	 * indication as defined in Section 7.2, it MAY conclude that a Success
       
  3343 	 * packet has been lost, and behave as if it had actually received a
       
  3344 	 * Success packet.  This includes choosing to ignore the Success in some
       
  3345 	 * circumstances as described in Section 4.2.
       
  3346 	 * Add call to current EAP-type. Maybe the EAP-Success packet could
       
  3347 	 * be created here and send to EAP-type.
       
  3348 	 * }
       
  3349 	 */
       
  3350 
       
  3351 	if (m_current_eap_type != eap_type_none)
       
  3352 	{
       
  3353 		// Here we query the current EAP-type.
       
  3354 		eap_variable_data_c selector(m_am_tools);
       
  3355 		u64_t selector_eap_type = convert_eap_type_to_u64_t(m_current_eap_type);
       
  3356 		status = selector.set_buffer(&selector_eap_type, sizeof(selector_eap_type), false, false);
       
  3357 		if (status != eap_status_ok)
       
  3358 		{
       
  3359 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3360 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3361 		}
       
  3362 		eap_base_type_c *handler = m_type_map.get_handler(&selector);
       
  3363 		
       
  3364 		// Check if we already have this type loaded.
       
  3365 		if (handler != 0)
       
  3366 		{
       
  3367 			status = handler->eap_acknowledge(receive_network_id);
       
  3368 
       
  3369 			if (status == eap_status_not_supported)
       
  3370 			{
       
  3371 				// This is too noisy.
       
  3372 				/**
       
  3373 				 * @{ 2004-09-02 Fix all eap_acknowledge() functions. }
       
  3374 				 */
       
  3375 				status = eap_status_ok;
       
  3376 			}
       
  3377 		}
       
  3378 		else
       
  3379 		{
       
  3380 			// Here we do not care of missing handler.
       
  3381 			// Acknowledge is meaningfull only for existing handler.
       
  3382 			status = eap_status_ok;
       
  3383 		}
       
  3384 	}
       
  3385 	else
       
  3386 	{
       
  3387 		// Here we do not care of missing handler.
       
  3388 		// Acknowledge is meaningfull only for existing handler.
       
  3389 		status = eap_status_ok;
       
  3390 	}
       
  3391 
       
  3392 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3393 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3394 }
       
  3395 
       
  3396 //--------------------------------------------------
       
  3397 
       
  3398 //
       
  3399 EAP_FUNC_EXPORT eap_status_e eap_core_c::restart_authentication(
       
  3400 	const eap_am_network_id_c * const send_network_id,
       
  3401 	const bool is_client_when_true)
       
  3402 {
       
  3403 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3404 
       
  3405 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3406 
       
  3407 	// Here we swap the addresses.
       
  3408 	eap_am_network_id_c receive_network_id(m_am_tools,
       
  3409 		send_network_id->get_destination_id(),
       
  3410 		send_network_id->get_source_id(),
       
  3411 		send_network_id->get_type());
       
  3412 
       
  3413 	eap_status_e status = eap_status_process_general_error;
       
  3414 
       
  3415 	initialize_session_timeout(m_session_timeout);
       
  3416 
       
  3417 	if (is_client_when_true == false)
       
  3418 	{
       
  3419 		// This is much faster.
       
  3420 		status = m_partner->restart_authentication(
       
  3421 			&receive_network_id,
       
  3422 			is_client_when_true,
       
  3423 			true);
       
  3424 		if (status != eap_status_ok)
       
  3425 		{
       
  3426 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3427 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3428 		}
       
  3429 
       
  3430 		m_client_restart_authentication_initiated = true;
       
  3431 	}
       
  3432 	else
       
  3433 	{
       
  3434 		if (m_client_restart_authentication_initiated == true)
       
  3435 		{
       
  3436 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3437 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3438 		}
       
  3439 
       
  3440 		// This is much faster.
       
  3441 		status = m_partner->restart_authentication(
       
  3442 			&receive_network_id,
       
  3443 			is_client_when_true,
       
  3444 			true);
       
  3445 		if (status != eap_status_ok)
       
  3446 		{
       
  3447 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3448 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3449 		}
       
  3450 
       
  3451 		m_client_restart_authentication_initiated = true;
       
  3452 	}
       
  3453 
       
  3454 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3455 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3456 }
       
  3457 
       
  3458 //--------------------------------------------------
       
  3459 
       
  3460 #if defined(USE_EAP_CORE_SERVER)
       
  3461 
       
  3462 //
       
  3463 EAP_FUNC_EXPORT eap_status_e eap_core_c::send_eap_identity_request(
       
  3464 	const eap_am_network_id_c * const receive_network_id)
       
  3465 {
       
  3466 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3467 
       
  3468 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3469 
       
  3470 	EAP_ASSERT(m_is_client == false);
       
  3471 
       
  3472 	eap_status_e status = eap_status_process_general_error;
       
  3473 
       
  3474 	EAP_TRACE_DEBUG(
       
  3475 		m_am_tools, 
       
  3476 		TRACE_FLAGS_DEFAULT, 
       
  3477 		(EAPL("eap_core_c::send_eap_identity_request(): %s, %s\n"),
       
  3478 		 (m_is_client == true) ? "client": "server",
       
  3479 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3480 		 ));
       
  3481 
       
  3482 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_core_c::send_eap_identity_request()");
       
  3483 
       
  3484 	if (receive_network_id->get_is_valid_data() == false)
       
  3485 	{
       
  3486 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3487 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3488 	}
       
  3489 
       
  3490 	// Here we swap the addresses.
       
  3491 	eap_am_network_id_c send_network_id(m_am_tools,
       
  3492 		receive_network_id->get_destination_id(),
       
  3493 		receive_network_id->get_source_id(),
       
  3494 		receive_network_id->get_type());
       
  3495 
       
  3496 	if (send_network_id.get_is_valid_data() == false)
       
  3497 	{
       
  3498 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3499 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3500 	}
       
  3501 
       
  3502 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3503 
       
  3504 	EAP_TRACE_DEBUG(
       
  3505 		m_am_tools, 
       
  3506 		TRACE_FLAGS_DEFAULT, 
       
  3507 		(EAPL("eap_core_c::send_eap_identity_request(): %s, %s, m_skip_eap_request_identity=%d, m_eap_identity_request_send=%d, m_eap_identity_response_accepted=%d\n"),
       
  3508 		 (m_is_client == true) ? "client": "server",
       
  3509 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3510 		 m_skip_eap_request_identity,
       
  3511 		 m_eap_identity_request_send,
       
  3512 		 m_eap_identity_response_accepted
       
  3513 		 ));
       
  3514 
       
  3515 	if (m_skip_eap_request_identity == true)
       
  3516 	{
       
  3517 		if (m_eap_identity_request_send == true)
       
  3518 		{
       
  3519 			// Do nothing, this have been done already.
       
  3520 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3521 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3522 		}
       
  3523 
       
  3524 		if (m_eap_identity.get_is_valid_data() == false)
       
  3525 		{
       
  3526 			// No saved EAP-Identity. Set an empty EAP-Identity.
       
  3527 			status = m_eap_identity.init(0ul);
       
  3528 			if (status != eap_status_ok)
       
  3529 			{
       
  3530 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3531 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3532 			}
       
  3533 		}
       
  3534 
       
  3535 		// We will skip EAP-Request/Identity and EAP-Response/Identity for testing purposes.
       
  3536 		// Now restart authentication with proposed EAP type.
       
  3537 		status = restart_with_new_type(
       
  3538 			m_default_eap_type,
       
  3539 			receive_network_id,
       
  3540 			0ul);
       
  3541 		if (status != eap_status_ok)
       
  3542 		{
       
  3543 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3544 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3545 		}
       
  3546 
       
  3547 		m_eap_identity_request_send = true;
       
  3548 		m_eap_identity_response_accepted = true;
       
  3549 	}
       
  3550 	else
       
  3551 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  3552 	{
       
  3553 		// Creates a identity request message.
       
  3554 		eap_buf_chain_wr_c request_packet(
       
  3555 			eap_write_buffer, 
       
  3556 			m_am_tools, 
       
  3557 			EAP_CORE_PACKET_BUFFER_LENGTH);
       
  3558 
       
  3559 		if (request_packet.get_is_valid() == false)
       
  3560 		{
       
  3561 			EAP_TRACE_ERROR(
       
  3562 				m_am_tools, 
       
  3563 				TRACE_FLAGS_DEFAULT, 
       
  3564 				(EAPL("send_eap_identity_request(): %s, %s, packet buffer corrupted.\n"),
       
  3565 				 (m_is_client == true) ? "client": "server",
       
  3566 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3567 				 ));
       
  3568 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3569 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3570 		}
       
  3571 
       
  3572 		u32_t buffer_size = EAP_CORE_PACKET_BUFFER_LENGTH;
       
  3573 		EAP_ASSERT_ALWAYS(m_MTU > m_trailer_length);
       
  3574 		if (m_MTU-m_trailer_length < buffer_size)
       
  3575 		{
       
  3576 			buffer_size = m_MTU-m_trailer_length;
       
  3577 		}
       
  3578 
       
  3579 		EAP_ASSERT_ALWAYS(buffer_size >= m_eap_header_offset);
       
  3580 		eap_header_wr_c eap_request(
       
  3581 			m_am_tools,
       
  3582 			request_packet.get_data_offset(
       
  3583 				m_eap_header_offset,
       
  3584 				(buffer_size-m_eap_header_offset)),
       
  3585 			(buffer_size-m_eap_header_offset));
       
  3586 
       
  3587 		if (eap_request.get_is_valid() == false)
       
  3588 		{
       
  3589 			EAP_TRACE_ERROR(
       
  3590 				m_am_tools, 
       
  3591 				TRACE_FLAGS_DEFAULT, 
       
  3592 				(EAPL("send_eap_identity_request(): %s, %s, packet buffer corrupted.\n"),
       
  3593 				 (m_is_client == true) ? "client": "server",
       
  3594 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3595 				 ));
       
  3596 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3597 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3598 		}
       
  3599 
       
  3600 		eap_request.set_length(
       
  3601 			static_cast<u16_t>((EAP_CORE_PACKET_BUFFER_LENGTH-m_eap_header_offset)),
       
  3602 			m_use_eap_expanded_type);
       
  3603 		eap_request.set_code(eap_code_request);
       
  3604 		eap_request.set_identifier(0);
       
  3605 		eap_request.set_type_data_length(0ul, m_use_eap_expanded_type);
       
  3606 		eap_request.set_type(eap_type_identity, m_use_eap_expanded_type);
       
  3607 
       
  3608 		request_packet.set_data_length(m_eap_header_offset+eap_request.get_length());
       
  3609 		request_packet.set_do_packet_retransmission(true);
       
  3610 
       
  3611 		EAP_ASSERT(m_eap_header_offset < request_packet.get_data_length());
       
  3612 		EAP_ASSERT(eap_request.get_length() <= request_packet.get_data_length());
       
  3613 		EAP_ASSERT(request_packet.get_data_length() <= EAP_CORE_PACKET_BUFFER_LENGTH);
       
  3614 
       
  3615 		status = packet_send(
       
  3616 			&send_network_id, &request_packet, m_eap_header_offset,
       
  3617 			eap_request.get_length(),
       
  3618 			EAP_CORE_PACKET_BUFFER_LENGTH);
       
  3619 
       
  3620 		if (status == eap_status_ok)
       
  3621 		{
       
  3622 			eap_state_notification_c notification(
       
  3623 				m_am_tools,
       
  3624 				&send_network_id,
       
  3625 				m_is_client,
       
  3626 				eap_state_notification_eap,
       
  3627 				eap_protocol_layer_eap,
       
  3628 				m_current_eap_type,
       
  3629 				eap_state_none,
       
  3630 				eap_state_identity_request_sent,
       
  3631 				eap_request.get_identifier(),
       
  3632 				false);
       
  3633 			state_notification(&notification);
       
  3634 		}
       
  3635 
       
  3636 		m_eap_identity_request_send = true;
       
  3637 	}
       
  3638 
       
  3639 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3640 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3641 }
       
  3642 
       
  3643 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  3644 
       
  3645 //--------------------------------------------------
       
  3646 
       
  3647 //
       
  3648 EAP_FUNC_EXPORT eap_status_e eap_core_c::send_eap_nak_response(
       
  3649 	const eap_am_network_id_c * const receive_network_id,
       
  3650 	const u8_t eap_identifier,
       
  3651 	const eap_array_c<eap_type_value_e> * const eap_type_list)
       
  3652 {
       
  3653 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3654 
       
  3655 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3656 
       
  3657 	eap_status_e status = eap_status_process_general_error;
       
  3658 
       
  3659 	EAP_TRACE_DEBUG(
       
  3660 		m_am_tools, 
       
  3661 		TRACE_FLAGS_DEFAULT, 
       
  3662 		(EAPL("eap_core_c::send_eap_nak_response(): %s, %s\n"),
       
  3663 		 (m_is_client == true) ? "client": "server",
       
  3664 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3665 		 ));
       
  3666 
       
  3667 	// Here we swap the addresses.
       
  3668 	eap_am_network_id_c send_network_id(m_am_tools,
       
  3669 		receive_network_id->get_destination_id(),
       
  3670 		receive_network_id->get_source_id(),
       
  3671 		receive_network_id->get_type());
       
  3672 
       
  3673 	// Creates a identity request message.
       
  3674 	eap_buf_chain_wr_c nak_packet(
       
  3675 		eap_write_buffer, 
       
  3676 		m_am_tools, 
       
  3677 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
  3678 
       
  3679 	if (nak_packet.get_is_valid() == false)
       
  3680 	{
       
  3681 		EAP_TRACE_ERROR(
       
  3682 			m_am_tools, 
       
  3683 			TRACE_FLAGS_DEFAULT, 
       
  3684 			(EAPL("eap_core_c::send_eap_nak_response(): %s, %s, packet buffer corrupted.\n"),
       
  3685 			 (m_is_client == true) ? "client": "server",
       
  3686 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3687 			 ));
       
  3688 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3689 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3690 	}
       
  3691 
       
  3692 	u32_t buffer_size = EAP_CORE_PACKET_BUFFER_LENGTH;
       
  3693 	EAP_ASSERT_ALWAYS(m_MTU > m_trailer_length);
       
  3694 	if (m_MTU-m_trailer_length < buffer_size)
       
  3695 	{
       
  3696 		buffer_size = m_MTU-m_trailer_length;
       
  3697 	}
       
  3698 
       
  3699 	EAP_ASSERT_ALWAYS(buffer_size >= m_eap_header_offset);
       
  3700 	eap_header_wr_c eap_nak_hdr(
       
  3701 		m_am_tools,
       
  3702 		nak_packet.get_data_offset(
       
  3703 			m_eap_header_offset,
       
  3704 			(buffer_size-m_eap_header_offset)),
       
  3705 		(buffer_size-m_eap_header_offset)
       
  3706 		);
       
  3707 
       
  3708 	if (eap_nak_hdr.get_is_valid() == false)
       
  3709 	{
       
  3710 		EAP_TRACE_ERROR(
       
  3711 			m_am_tools, 
       
  3712 			TRACE_FLAGS_DEFAULT, 
       
  3713 			(EAPL("eap_core_c::send_eap_nak_response(): %s, %s, packet buffer corrupted.\n"),
       
  3714 			 (m_is_client == true) ? "client": "server",
       
  3715 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3716 			 ));
       
  3717 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3718 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3719 	}
       
  3720 
       
  3721 	bool write_expanded_type(false);
       
  3722 	u32_t ind = 0ul;
       
  3723 	u32_t count_of_eap_types = eap_type_list->get_object_count();
       
  3724 
       
  3725 	for (ind = 0ul; ind < count_of_eap_types; ind++)
       
  3726 	{
       
  3727 		const eap_type_value_e * const type = eap_type_list->get_object(ind);
       
  3728 		if (type != 0
       
  3729 			&& eap_expanded_type_c::is_ietf_type(*type) == false)
       
  3730 		{
       
  3731 			write_expanded_type = true;
       
  3732 			break;
       
  3733 		}
       
  3734 	}
       
  3735 
       
  3736 	eap_nak_hdr.set_length(
       
  3737 		static_cast<u16_t>((EAP_CORE_PACKET_BUFFER_LENGTH-m_eap_header_offset)),
       
  3738 		write_expanded_type);
       
  3739 	eap_nak_hdr.set_code(eap_code_response);
       
  3740 	eap_nak_hdr.set_identifier(eap_identifier);
       
  3741 	eap_nak_hdr.set_type_data_length(eap_nak_hdr.get_length(), write_expanded_type);
       
  3742 	eap_nak_hdr.set_type(eap_type_nak, write_expanded_type);
       
  3743 
       
  3744 	u32_t required_data_length = count_of_eap_types
       
  3745 		*eap_expanded_type_c::get_eap_expanded_type_size();
       
  3746 
       
  3747 	if (eap_nak_hdr.get_length() < required_data_length)
       
  3748 	{
       
  3749 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3750 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3751 	}
       
  3752 
       
  3753 	u32_t type_length = eap_expanded_type_c::m_ietf_type_size;
       
  3754 	if (write_expanded_type == true)
       
  3755 	{
       
  3756 		type_length = eap_expanded_type_c::m_eap_expanded_type_size;
       
  3757 	}
       
  3758 
       
  3759 	u8_t * const type_data = eap_nak_hdr.get_data_offset(type_length, required_data_length);
       
  3760 
       
  3761 	if (type_data == 0)
       
  3762 	{
       
  3763 		EAP_TRACE_ERROR(
       
  3764 			m_am_tools, 
       
  3765 			TRACE_FLAGS_DEFAULT, 
       
  3766 			(EAPL("eap_core_c::send_eap_nak_response(): %s, %s, packet buffer corrupted.\n"),
       
  3767 			 (m_is_client == true) ? "client": "server",
       
  3768 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3769 			 ));
       
  3770 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3771 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3772 	}
       
  3773 
       
  3774 
       
  3775 	u8_t * const data = type_data;
       
  3776 
       
  3777 	for (ind = 0ul; ind < count_of_eap_types; ind++)
       
  3778 	{
       
  3779 		const eap_type_value_e * const type = eap_type_list->get_object(ind);
       
  3780 
       
  3781 		if (type != 0)
       
  3782 		{
       
  3783 			EAP_TRACE_DEBUG(
       
  3784 				m_am_tools, 
       
  3785 				TRACE_FLAGS_DEFAULT, 
       
  3786 				(EAPL("%s: eap_core_c::send_eap_nak_response(): allowed EAP-type %d.\n"),
       
  3787 				 (m_is_client == true ? "client": "server"),
       
  3788 				 convert_eap_type_to_u32_t(*type)));
       
  3789 
       
  3790 			status = eap_expanded_type_c::write_type(
       
  3791 				m_am_tools,
       
  3792 				ind,
       
  3793 				data,
       
  3794 				eap_nak_hdr.get_type_data_length()
       
  3795 				-eap_expanded_type_c::get_eap_expanded_type_size()*ind,
       
  3796 				write_expanded_type,
       
  3797 				*type);
       
  3798 		}
       
  3799 		else
       
  3800 		{
       
  3801 			EAP_TRACE_ERROR(
       
  3802 				m_am_tools, 
       
  3803 				TRACE_FLAGS_DEFAULT, 
       
  3804 				(EAPL("eap_core_c::send_eap_nak_response(): %s, %s, ")
       
  3805 				 EAPL("No EAP-type supported.\n"),
       
  3806 				 (m_is_client == true) ? "client": "server",
       
  3807 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"));
       
  3808 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3809 			return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  3810 		}
       
  3811 	} // for()
       
  3812 
       
  3813 	eap_nak_hdr.set_type_data_length(
       
  3814 		static_cast<u16_t>(count_of_eap_types*type_length),
       
  3815 		write_expanded_type);
       
  3816 	nak_packet.set_data_length(m_eap_header_offset+eap_nak_hdr.get_length());
       
  3817 
       
  3818 	EAP_ASSERT(m_eap_header_offset < nak_packet.get_data_length());
       
  3819 	EAP_ASSERT(eap_nak_hdr.get_length() <= nak_packet.get_data_length());
       
  3820 	EAP_ASSERT(nak_packet.get_data_length() <= EAP_CORE_PACKET_BUFFER_LENGTH);
       
  3821 
       
  3822 	status = packet_send(
       
  3823 		&send_network_id, &nak_packet, m_eap_header_offset,
       
  3824 		eap_nak_hdr.get_length(),
       
  3825 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
  3826 
       
  3827 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3828 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3829 }
       
  3830 
       
  3831 //--------------------------------------------------
       
  3832 
       
  3833 EAP_FUNC_EXPORT eap_status_e eap_core_c::packet_data_crypto_keys(
       
  3834 	const eap_am_network_id_c * const send_network_id,
       
  3835 	const eap_master_session_key_c * const master_session_key
       
  3836 	)
       
  3837 {
       
  3838 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3839 
       
  3840 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3841 
       
  3842 	const eap_status_e status = m_partner->packet_data_crypto_keys(
       
  3843 		send_network_id,
       
  3844 		master_session_key);
       
  3845 
       
  3846 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3847 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3848 }
       
  3849 
       
  3850 //--------------------------------------------------
       
  3851 
       
  3852 EAP_FUNC_EXPORT eap_status_e eap_core_c::read_configure(
       
  3853 	const eap_configuration_field_c * const field,
       
  3854 	eap_variable_data_c * const data)
       
  3855 {
       
  3856 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3857 
       
  3858 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3859 
       
  3860 	const eap_status_e status = m_partner->read_configure(field, data);
       
  3861 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3862 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3863 }
       
  3864 
       
  3865 //--------------------------------------------------
       
  3866 
       
  3867 EAP_FUNC_EXPORT eap_status_e eap_core_c::write_configure(
       
  3868 	const eap_configuration_field_c * const field,
       
  3869 	eap_variable_data_c * const data)
       
  3870 {
       
  3871 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3872 
       
  3873 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3874 
       
  3875 	const eap_status_e status = m_partner->write_configure(field, data);
       
  3876 
       
  3877 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3878 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3879 }
       
  3880 
       
  3881 //--------------------------------------------------
       
  3882 
       
  3883 //
       
  3884 EAP_FUNC_EXPORT eap_status_e eap_core_c::timer_expired(
       
  3885 	const u32_t id, void *data)
       
  3886 {
       
  3887 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3888 
       
  3889 	EAP_UNREFERENCED_PARAMETER(data); // Only trace uses this.
       
  3890 	
       
  3891 	EAP_TRACE_DEBUG(
       
  3892 		m_am_tools,
       
  3893 		TRACE_FLAGS_DEFAULT,
       
  3894 		(EAPL("TIMER: [0x%08x]->eap_core_c::timer_expired(id 0x%02x, data 0x%08x), %s, %s.\n"),
       
  3895 		 this,
       
  3896 		 id,
       
  3897 		 data,
       
  3898 		 (m_is_client == true) ? "client": "server",
       
  3899 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"));
       
  3900 
       
  3901 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  3902 
       
  3903 	eap_status_e status = eap_status_process_general_error;
       
  3904 
       
  3905 	if (id == EAP_CORE_FAILURE_RECEIVED_ID)
       
  3906 	{
       
  3907 		EAP_TRACE_DEBUG(
       
  3908 			m_am_tools, 
       
  3909 			TRACE_FLAGS_DEFAULT, 
       
  3910 			(EAPL("TIMER: %s: %s, EAP_CORE_FAILURE_RECEIVED_ID elapsed.\n"),
       
  3911 			 (m_is_client == true ? "client": "server"),
       
  3912 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3913 			 ));
       
  3914 
       
  3915 		{
       
  3916 			eap_am_network_id_c send_network_id(m_am_tools,
       
  3917 				m_receive_network_id.get_destination_id(),
       
  3918 				m_receive_network_id.get_source_id(),
       
  3919 				m_receive_network_id.get_type());
       
  3920 
       
  3921 			eap_state_notification_c notification(
       
  3922 				m_am_tools,
       
  3923 				&send_network_id,
       
  3924 				m_is_client,
       
  3925 				eap_state_notification_eap,
       
  3926 				eap_protocol_layer_eap,
       
  3927 				m_current_eap_type,
       
  3928 				eap_state_none,
       
  3929 				eap_state_authentication_terminated_unsuccessfully,
       
  3930 				m_eap_identity_request_identifier_client,
       
  3931 				false);
       
  3932 
       
  3933 			notification.set_authentication_error(eap_status_authentication_failure);
       
  3934 
       
  3935 			state_notification(&notification);
       
  3936 		}
       
  3937 
       
  3938 		status = eap_status_ok;
       
  3939 	}
       
  3940 	else if (id == EAP_CORE_TIMER_RETRANSMISSION_ID)
       
  3941 	{
       
  3942 		EAP_TRACE_DEBUG(
       
  3943 			m_am_tools, 
       
  3944 			TRACE_FLAGS_DEFAULT, 
       
  3945 			(EAPL("TIMER: %s: %s, EAP_CORE_TIMER_RETRANSMISSION_ID elapsed.\n"),
       
  3946 			 (m_is_client == true ? "client": "server"),
       
  3947 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  3948 			 ));
       
  3949 
       
  3950 		if (m_retransmission != 0
       
  3951 			&& m_retransmission->get_is_valid() == true
       
  3952 			&& m_retransmission->get_retransmission_counter() > 0)
       
  3953 		{
       
  3954 			EAP_TRACE_DEBUG(
       
  3955 				m_am_tools,
       
  3956 				TRACE_FLAGS_DEFAULT,
       
  3957 				(EAPL("TIMER: %s, %s, new retransmission, m_retransmission->get_is_valid()=%d, ")
       
  3958 				 EAPL("m_retransmission->get_retransmission_counter()=%d.\n"),
       
  3959 				 (m_is_client == true) ? "client": "server",
       
  3960 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  3961 				 m_retransmission->get_is_valid(),
       
  3962 				 m_retransmission->get_retransmission_counter()));
       
  3963 
       
  3964 			// This packet send is initialized by timer event.
       
  3965 
       
  3966 			status = resend_packet(
       
  3967 				m_retransmission->get_send_network_id(),
       
  3968 				m_retransmission->get_sent_packet(),
       
  3969 				m_retransmission->get_header_offset(),
       
  3970 				m_retransmission->get_data_length(),
       
  3971 				m_retransmission->get_buffer_size(),
       
  3972 				m_retransmission->get_retransmission_counter()
       
  3973 				);
       
  3974 
       
  3975 			if (status == eap_status_ok)
       
  3976 			{
       
  3977 				if (m_retransmission->get_retransmission_counter() > 0u)
       
  3978 				{
       
  3979 					// OK, initialize the next time to retransmit.
       
  3980 					u32_t next_retransmission_time
       
  3981 						= m_retransmission->get_next_retransmission_time();
       
  3982 
       
  3983 					status = m_partner->set_timer(
       
  3984 						this,
       
  3985 						EAP_CORE_TIMER_RETRANSMISSION_ID,
       
  3986 						0,
       
  3987 						next_retransmission_time);
       
  3988 					if (status != eap_status_ok)
       
  3989 					{
       
  3990 						delete m_retransmission;
       
  3991 						m_retransmission = 0;
       
  3992 					}
       
  3993 					else
       
  3994 					{
       
  3995 						m_retransmission->get_next_retransmission_counter(); // This decrements the counter.
       
  3996 
       
  3997 						EAP_TRACE_DEBUG(
       
  3998 							m_am_tools, 
       
  3999 							TRACE_FLAGS_DEFAULT, 
       
  4000 							(EAPL("TIMER: %s: %s, EAP_CORE_TIMER_RETRANSMISSION_ID ")
       
  4001 							 EAPL("set %d ms, retransmission_counter %d.\n"),
       
  4002 							 (m_is_client == true ? "client": "server"),
       
  4003 							 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  4004 							 next_retransmission_time,
       
  4005 							 m_retransmission->get_retransmission_counter()));
       
  4006 					}
       
  4007 				}
       
  4008 
       
  4009 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4010 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4011 			}
       
  4012 			else
       
  4013 			{
       
  4014 				delete m_retransmission;
       
  4015 				m_retransmission = 0;
       
  4016 
       
  4017 				status = eap_status_ok;
       
  4018 
       
  4019 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4020 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4021 			}
       
  4022 		}
       
  4023 		else
       
  4024 		{
       
  4025 			EAP_TRACE_DEBUG(
       
  4026 				m_am_tools, 
       
  4027 				TRACE_FLAGS_DEFAULT, 
       
  4028 				(EAPL("TIMER: %s, %s, no retransmission, m_retransmission=0x%08x.\n"),
       
  4029 				 (m_is_client == true) ? "client": "server",
       
  4030 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  4031 				 m_retransmission));
       
  4032 			if (m_retransmission != 0)
       
  4033 			{
       
  4034 				EAP_TRACE_DEBUG(
       
  4035 					m_am_tools, 
       
  4036 					TRACE_FLAGS_DEFAULT, 
       
  4037 					(EAPL("TIMER: %s, %s, no retransmission, m_retransmission->get_is_valid()=%d, ")
       
  4038 					 EAPL("m_retransmission->get_retransmission_counter()=%d.\n"),
       
  4039 					 (m_is_client == true) ? "client": "server",
       
  4040 					 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  4041 					 m_retransmission->get_is_valid(),
       
  4042 					 m_retransmission->get_retransmission_counter()));
       
  4043 			}
       
  4044 
       
  4045 			// No good EAP-Response received to EAP-Requests.
       
  4046 			// Terminate the session.
       
  4047 
       
  4048 			{
       
  4049 				eap_am_network_id_c send_network_id(m_am_tools,
       
  4050 					m_receive_network_id.get_destination_id(),
       
  4051 					m_receive_network_id.get_source_id(),
       
  4052 					m_receive_network_id.get_type());
       
  4053 
       
  4054 				eap_state_notification_c notification(
       
  4055 					m_am_tools,
       
  4056 					&send_network_id,
       
  4057 					m_is_client,
       
  4058 					eap_state_notification_eap,
       
  4059 					eap_protocol_layer_eap,
       
  4060 					m_current_eap_type,
       
  4061 					eap_state_none,
       
  4062 					eap_state_authentication_terminated_unsuccessfully,
       
  4063 					m_eap_identity_request_identifier_client,
       
  4064 					false);
       
  4065 
       
  4066 				notification.set_authentication_error(eap_status_authentication_failure);
       
  4067 
       
  4068 				state_notification(&notification);
       
  4069 			}
       
  4070 
       
  4071 			status = eap_status_ok;
       
  4072 		}
       
  4073 	}
       
  4074 #if defined(USE_EAP_CORE_SERVER)
       
  4075 	else if (id == EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID)
       
  4076 	{
       
  4077 		// Now restart authentication with proposed EAP type.
       
  4078 		const eap_core_nak_info_c * const nak_info
       
  4079 			= reinterpret_cast<const eap_core_nak_info_c *>(data);
       
  4080 		
       
  4081 		EAP_TRACE_DEBUG(
       
  4082 			m_am_tools, 
       
  4083 			TRACE_FLAGS_DEFAULT, 
       
  4084 			(EAPL("TIMER: %s: %s, EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID elapsed.\n"),
       
  4085 			 (m_is_client == true ? "client": "server"),
       
  4086 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4087 			 ));
       
  4088 
       
  4089 		eap_type_value_e used_eap_type = nak_info->get_proposed_eap_type();
       
  4090 
       
  4091 		m_nak_process_timer_active = false;
       
  4092 
       
  4093 		{
       
  4094 			// First remove current EAP-type.
       
  4095 			eap_variable_data_c selector(m_am_tools);
       
  4096 			status = selector.set_copy_of_buffer(
       
  4097 				&m_current_eap_type,
       
  4098 				sizeof(m_current_eap_type));
       
  4099 			if (status != eap_status_ok)
       
  4100 			{
       
  4101 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4102 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4103 			}
       
  4104 			eap_base_type_c *handler = m_type_map.get_handler(&selector);
       
  4105 
       
  4106 			// Change the current EAP-type here because shutdown could
       
  4107 			// cause state notifications from old EAP-type.
       
  4108 			m_current_eap_type = used_eap_type;
       
  4109 
       
  4110 			if (handler != 0)
       
  4111 			{
       
  4112 				status = handler->shutdown();
       
  4113 				if (status != eap_status_ok)
       
  4114 				{
       
  4115 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4116 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4117 				}
       
  4118 
       
  4119 				status = m_type_map.remove_handler(&selector, true);
       
  4120 				if (status != eap_status_ok)
       
  4121 				{
       
  4122 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4123 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4124 				}
       
  4125 			}
       
  4126 
       
  4127 			// Now restart authentication with proposed EAP type.
       
  4128 			status = restart_with_new_type(
       
  4129 				used_eap_type,
       
  4130 				nak_info->get_network_id(),
       
  4131 				nak_info->get_eap_identifier());
       
  4132 
       
  4133 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4134 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4135 		}
       
  4136 	}
       
  4137 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4138 	else if (id == EAP_CORE_SESSION_TIMEOUT_ID
       
  4139 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4140 				|| id == EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID
       
  4141 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4142 		)
       
  4143 	{
       
  4144 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4145 		if (id == EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID)
       
  4146 		{
       
  4147 			EAP_TRACE_DEBUG(
       
  4148 				m_am_tools, 
       
  4149 				TRACE_FLAGS_DEFAULT, 
       
  4150 				(EAPL("TIMER: %s: %s, EAP_CORE_WAIT_EAP_REQUEST_TYPE_ID elapsed.\n"),
       
  4151 				 (m_is_client == true ? "client": "server"),
       
  4152 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4153 				 ));
       
  4154 		}
       
  4155 		else
       
  4156 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4157 		{
       
  4158 			EAP_TRACE_DEBUG(
       
  4159 				m_am_tools, 
       
  4160 				TRACE_FLAGS_DEFAULT, 
       
  4161 				(EAPL("TIMER: %s: %s, EAP_CORE_SESSION_TIMEOUT_ID elapsed.\n"),
       
  4162 				 (m_is_client == true ? "client": "server"),
       
  4163 				 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4164 				 ));
       
  4165 		}
       
  4166 
       
  4167 		// we will remove this session immediately.
       
  4168 		status = initialize_asynchronous_init_remove_eap_session(0ul);
       
  4169 
       
  4170 		eap_am_network_id_c send_network_id(m_am_tools,
       
  4171 				m_receive_network_id.get_destination_id(),
       
  4172 				m_receive_network_id.get_source_id(),
       
  4173 				m_receive_network_id.get_type());
       
  4174 
       
  4175 		eap_state_notification_c notification(
       
  4176 			m_am_tools,
       
  4177 			&send_network_id,
       
  4178 			m_is_client,
       
  4179 			eap_state_notification_eap,
       
  4180 			eap_protocol_layer_eap,
       
  4181 			m_current_eap_type,
       
  4182 			eap_state_none,
       
  4183 			eap_state_authentication_terminated_unsuccessfully,
       
  4184 			m_eap_identity_request_identifier_client,
       
  4185 			false);
       
  4186 
       
  4187 		notification.set_authentication_error(eap_status_authentication_failure);
       
  4188 
       
  4189 		state_notification(&notification);
       
  4190 
       
  4191 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4192 	}
       
  4193 	else if (id == EAP_CORE_REMOVE_SESSION_TIMEOUT_ID)
       
  4194 	{
       
  4195 		EAP_TRACE_DEBUG(
       
  4196 			m_am_tools, 
       
  4197 			TRACE_FLAGS_DEFAULT, 
       
  4198 			(EAPL("TIMER: %s: %s, EAP_CORE_REMOVE_SESSION_TIMEOUT_ID elapsed.\n"),
       
  4199 			 (m_is_client == true ? "client": "server"),
       
  4200 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4201 			 ));
       
  4202 
       
  4203 		status = asynchronous_init_remove_eap_session();
       
  4204 	}
       
  4205 
       
  4206 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4207 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4208 }
       
  4209 
       
  4210 //--------------------------------------------------
       
  4211 
       
  4212 //
       
  4213 EAP_FUNC_EXPORT eap_status_e eap_core_c::timer_delete_data(
       
  4214 	const u32_t id, void *data)
       
  4215 {
       
  4216 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4217 
       
  4218 	EAP_UNREFERENCED_PARAMETER(data); // Only trace uses this.
       
  4219 
       
  4220 	EAP_TRACE_DEBUG(
       
  4221 		m_am_tools, 
       
  4222 		TRACE_FLAGS_DEFAULT, 
       
  4223 		(EAPL("TIMER: [0x%08x]->eap_core_c::timer_delete_data(id 0x%02x, data 0x%08x): %s, %s.\n"),
       
  4224 		 this,
       
  4225 		 id,
       
  4226 		 data,
       
  4227 		 (m_is_client == true) ? "client": "server",
       
  4228 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4229 		 ));
       
  4230 
       
  4231 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  4232 
       
  4233 	if (id == EAP_CORE_TIMER_RETRANSMISSION_ID)
       
  4234 	{
       
  4235 		EAP_TRACE_DEBUG(
       
  4236 			m_am_tools, 
       
  4237 			TRACE_FLAGS_DEFAULT, 
       
  4238 			(EAPL("TIMER: %s: %s, EAP_CORE_TIMER_RETRANSMISSION_ID delete data.\n"),
       
  4239 			 (m_is_client == true ? "client": "server"),
       
  4240 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4241 			 ));
       
  4242 
       
  4243 		if (m_retransmission != 0
       
  4244 			&& m_retransmission->get_is_valid() == true
       
  4245 			&& m_retransmission->get_retransmission_counter() > 0)
       
  4246 		{
       
  4247 			// Do not delete yet.
       
  4248 			// cancel_retransmission() will delete m_retransmission.
       
  4249 		}
       
  4250 		else if (m_retransmission != 0)
       
  4251 		{
       
  4252 			delete m_retransmission;
       
  4253 			m_retransmission = 0;
       
  4254 		}
       
  4255 	}
       
  4256 #if defined(USE_EAP_CORE_SERVER)
       
  4257 	else if (id == EAP_CORE_DELAYED_EAP_NAK_PROCESS_ID)
       
  4258 	{
       
  4259 		const eap_core_nak_info_c * const nak_info
       
  4260 			= reinterpret_cast<const eap_core_nak_info_c *>(data);
       
  4261 		delete nak_info;
       
  4262 	}
       
  4263 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4264 	else if (id == EAP_CORE_REMOVE_SESSION_TIMEOUT_ID)
       
  4265 	{
       
  4266 		// Nothing to do.
       
  4267 	}
       
  4268 
       
  4269 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4270 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4271 }
       
  4272 
       
  4273 //--------------------------------------------------
       
  4274 
       
  4275 //
       
  4276 EAP_FUNC_EXPORT eap_status_e eap_core_c::reset_operation(
       
  4277 	eap_base_type_c * const handler,
       
  4278 	abs_eap_am_tools_c * const m_am_tools)
       
  4279 {
       
  4280 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4281 
       
  4282 	EAP_UNREFERENCED_PARAMETER(m_am_tools);
       
  4283 
       
  4284 	EAP_TRACE_ALWAYS(
       
  4285 		m_am_tools, 
       
  4286 		TRACE_FLAGS_DEFAULT, 
       
  4287 		(EAPL("eap_core_c::reset_operation(): handler=0x%08x.\n"),
       
  4288 		 handler));
       
  4289 
       
  4290 	eap_status_e status = handler->reset();
       
  4291 
       
  4292 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4293 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4294 }
       
  4295 
       
  4296 //--------------------------------------------------
       
  4297 
       
  4298 //
       
  4299 EAP_FUNC_EXPORT eap_status_e eap_core_c::reset()
       
  4300 {
       
  4301 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4302 
       
  4303 #if !defined(USE_EAP_DEBUG_TRACE)
       
  4304 	EAP_TRACE_ALWAYS(
       
  4305 		m_am_tools, 
       
  4306 		TRACE_FLAGS_DEFAULT, 
       
  4307 		(EAPL("eap_core_c::reset(): %s: %s.\n"),
       
  4308 		 ((m_is_client == true) ? "client": "server"),
       
  4309 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most"));
       
  4310 #else
       
  4311 	EAP_TRACE_ALWAYS(
       
  4312 		m_am_tools, 
       
  4313 		TRACE_FLAGS_DEFAULT, 
       
  4314 		(EAPL("eap_core_c::reset(): %s: %s, this = 0x%08x => 0x%08x.\n"),
       
  4315 		 ((m_is_client == true) ? "client": "server"),
       
  4316 		 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  4317 		 this,
       
  4318 		 dynamic_cast<abs_eap_base_timer_c *>(this)));
       
  4319 #endif
       
  4320 
       
  4321 	eap_status_e status = eap_status_ok;
       
  4322 
       
  4323 	eap_variable_data_c selector(m_am_tools);
       
  4324 	u64_t tmp_eap_type = convert_eap_type_to_u64_t(m_current_eap_type);
       
  4325 	status = selector.set_buffer(&tmp_eap_type, sizeof(tmp_eap_type), false, false);
       
  4326 	if (status != eap_status_ok)
       
  4327 	{
       
  4328 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4329 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4330 	}
       
  4331 
       
  4332 	cancel_retransmission();
       
  4333 
       
  4334 	cancel_session_timeout();
       
  4335 
       
  4336 	cancel_eap_failure_timeout();
       
  4337 
       
  4338 	cancel_asynchronous_init_remove_eap_session();
       
  4339 
       
  4340 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4341 
       
  4342 	if (m_is_tunneled_eap == false
       
  4343 		&& m_is_client_role == true)
       
  4344 	{
       
  4345 		status = cancel_wait_eap_request_type_timeout();
       
  4346 		if (status != eap_status_ok)
       
  4347 		{
       
  4348 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4349 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4350 		}
       
  4351 
       
  4352 		status = set_wait_eap_request_type_timeout();
       
  4353 		if (status != eap_status_ok)
       
  4354 		{
       
  4355 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4356 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4357 		}
       
  4358 	}
       
  4359 
       
  4360 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4361 
       
  4362 	m_eap_identity_response_accepted = false;
       
  4363 	m_eap_type_response_sent = false;
       
  4364 
       
  4365 #if defined(USE_EAP_CORE_SERVER)
       
  4366 	m_eap_identity_request_send = false;
       
  4367 	m_eap_identity_response_received = false;
       
  4368 	m_eap_failure_sent = false;
       
  4369 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4370 
       
  4371 	m_ignore_eap_failure = false;
       
  4372 
       
  4373 	status = m_type_map.for_each(reset_operation, true);
       
  4374 	if (status != eap_status_ok)
       
  4375 	{
       
  4376 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4377 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4378 	}
       
  4379 
       
  4380 	m_current_eap_type = eap_type_none;
       
  4381 	m_eap_identity.reset();
       
  4382 
       
  4383 	// Add session timeout.
       
  4384 	initialize_session_timeout(m_session_timeout);
       
  4385 
       
  4386 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4387 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4388 }
       
  4389 
       
  4390 //--------------------------------------------------
       
  4391 
       
  4392 // 
       
  4393 EAP_FUNC_EXPORT eap_status_e eap_core_c::handle_eap_identity_request(
       
  4394 	const eap_type_value_e used_eap_type,
       
  4395 	const u8_t eap_identifier,
       
  4396 	const eap_am_network_id_c * const receive_network_id)
       
  4397 {
       
  4398 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4399 
       
  4400 	eap_status_e status = eap_status_process_general_error;
       
  4401 
       
  4402 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4403 
       
  4404 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4405 
       
  4406 	if (m_is_tunneled_eap == false
       
  4407 		&& m_is_client_role == true)
       
  4408 	{
       
  4409 		status = cancel_wait_eap_request_type_timeout();
       
  4410 		if (status != eap_status_ok)
       
  4411 		{
       
  4412 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4413 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4414 		}
       
  4415 	}
       
  4416 
       
  4417 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  4418 
       
  4419 	// Here we query the desired EAP-type.
       
  4420 	eap_variable_data_c selector(m_am_tools);
       
  4421 	u64_t tmp_used_eap_type = convert_eap_type_to_u64_t(used_eap_type);
       
  4422 	status = selector.set_buffer(&tmp_used_eap_type, sizeof(tmp_used_eap_type), false, false);
       
  4423 	if (status != eap_status_ok)
       
  4424 	{
       
  4425 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4426 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4427 	}
       
  4428 
       
  4429 	eap_base_type_c *handler = m_type_map.get_handler(&selector);
       
  4430 
       
  4431 	if (handler == 0
       
  4432 		|| handler->get_is_valid() == false)
       
  4433 	{
       
  4434 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4435 		return EAP_STATUS_RETURN(m_am_tools, eap_status_type_does_not_exists_error);
       
  4436 	}
       
  4437 
       
  4438 	m_client_restart_authentication_initiated = false;
       
  4439 
       
  4440 	// Here we swap the addresses.
       
  4441 	eap_am_network_id_c send_network_id(m_am_tools,
       
  4442 		receive_network_id->get_destination_id(),
       
  4443 		receive_network_id->get_source_id(),
       
  4444 		receive_network_id->get_type());
       
  4445 
       
  4446 
       
  4447 	// Send state change notification
       
  4448 	eap_state_notification_c notification(
       
  4449 		m_am_tools,
       
  4450 		&send_network_id,
       
  4451 		m_is_client,
       
  4452 		eap_state_notification_eap,
       
  4453 		eap_protocol_layer_eap,
       
  4454 		m_current_eap_type,
       
  4455 		eap_state_none,
       
  4456 		eap_state_identity_request_received,
       
  4457 		eap_identifier,
       
  4458 		false);
       
  4459 	state_notification(&notification);
       
  4460 
       
  4461 	// Save EAP-identifier
       
  4462 	m_eap_identity_request_identifier_client = eap_identifier;
       
  4463 
       
  4464 	status = handler->query_eap_identity(
       
  4465 		false,
       
  4466 		&m_eap_identity,
       
  4467 		receive_network_id,
       
  4468 		eap_identifier);
       
  4469 	if (status == eap_status_drop_packet_quietly)
       
  4470 	{
       
  4471 		// This packet was dropped.
       
  4472 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4473 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4474 	}
       
  4475 	else if (status == eap_status_pending_request)
       
  4476 	{
       
  4477 		// This is pending query, that will be completed by complete_eap_identity_query() call.
       
  4478 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4479 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4480 	}
       
  4481 	else if (status == eap_status_completed_request)
       
  4482 	{
       
  4483 		// This is already completed by complete_eap_identity_query() call.
       
  4484 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4485 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4486 	}
       
  4487 	else if (status != eap_status_ok)
       
  4488 	{
       
  4489 		// Send failure notification
       
  4490 		eap_state_notification_c notification(
       
  4491 			m_am_tools,
       
  4492 			&send_network_id,
       
  4493 			m_is_client,
       
  4494 			eap_state_notification_eap,
       
  4495 			eap_protocol_layer_eap,
       
  4496 			m_current_eap_type,
       
  4497 			eap_state_none,
       
  4498 			eap_state_authentication_terminated_unsuccessfully,
       
  4499 			eap_identifier,
       
  4500 			false);
       
  4501 
       
  4502 		notification.set_authentication_error(eap_status_authentication_failure);
       
  4503 
       
  4504 		state_notification(&notification);
       
  4505 
       
  4506 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4507 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4508 	}
       
  4509 	else // status == eap_status_ok
       
  4510 	{
       
  4511 		// The query_eap_identity() function call is synchronous.
       
  4512 		// We must call send_eap_identity_response().
       
  4513 
       
  4514 		status = send_eap_identity_response(
       
  4515 			&send_network_id,
       
  4516 			&m_eap_identity,
       
  4517 			m_eap_identity_request_identifier_client); // Uses the EAP-Identifier from the latest EAP-Request/Identity.
       
  4518 	}
       
  4519 
       
  4520 
       
  4521 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4522 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4523 }
       
  4524 
       
  4525 //--------------------------------------------------
       
  4526 
       
  4527 #if defined(USE_EAP_CORE_SERVER)
       
  4528 
       
  4529 // 
       
  4530 EAP_FUNC_EXPORT eap_status_e eap_core_c::handle_eap_identity_response(
       
  4531 	eap_base_type_c * const handler,
       
  4532 	const eap_type_value_e used_eap_type,
       
  4533 	const eap_am_network_id_c * const receive_network_id,
       
  4534 	eap_header_wr_c * const eap,
       
  4535 	const u32_t packet_length)
       
  4536 {
       
  4537 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4538 	EAP_UNREFERENCED_PARAMETER(used_eap_type); 
       
  4539 
       
  4540 	eap_status_e status = eap_status_process_general_error;
       
  4541 
       
  4542 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4543 
       
  4544 	EAP_ASSERT(m_is_client == false);
       
  4545 
       
  4546 	if (handler == 0)
       
  4547 	{
       
  4548 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4549 		return EAP_STATUS_RETURN(m_am_tools, eap_status_type_does_not_exists_error);
       
  4550 	}
       
  4551 
       
  4552 	status = handler->packet_process(
       
  4553 		receive_network_id,
       
  4554 		eap,
       
  4555 		packet_length);
       
  4556 
       
  4557 	if (status == eap_status_ok)
       
  4558 	{
       
  4559 		// We need to copy EAP-Identity for later use.
       
  4560 
       
  4561 		const u8_t * identity = eap->get_type_data(eap->get_type_data_length());
       
  4562 		const u32_t identity_length = eap->get_type_data_length();
       
  4563 		const u8_t empty_identity[] = "";
       
  4564 
       
  4565 		if (identity == 0
       
  4566 			|| identity_length == 0ul)
       
  4567 		{
       
  4568 			identity = empty_identity;
       
  4569 		}
       
  4570 
       
  4571 		status = m_eap_identity.set_copy_of_buffer(
       
  4572 			identity,
       
  4573 			identity_length);
       
  4574 	}
       
  4575 
       
  4576 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4577 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4578 }
       
  4579 
       
  4580 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4581 
       
  4582 //--------------------------------------------------
       
  4583 
       
  4584 #if defined(USE_EAP_CORE_SERVER)
       
  4585 
       
  4586 //
       
  4587 EAP_FUNC_EXPORT eap_status_e eap_core_c::send_eap_success(
       
  4588 	const eap_am_network_id_c * const send_network_id,
       
  4589 	const u8_t eap_identifier)
       
  4590 {
       
  4591 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4592 
       
  4593 	eap_buf_chain_wr_c eap_success_packet(
       
  4594 		eap_write_buffer, 
       
  4595 		m_am_tools, 
       
  4596 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
  4597 
       
  4598 	if (eap_success_packet.get_is_valid() == false)
       
  4599 	{
       
  4600 		EAP_TRACE_ERROR(
       
  4601 			m_am_tools, 
       
  4602 			TRACE_FLAGS_DEFAULT, 
       
  4603 			(EAPL("eap_core_c::send_eap_success(): packet buffer corrupted: %s, %s\n"),
       
  4604 			 (m_is_client == true) ? "client": "server",
       
  4605 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4606 			 ));
       
  4607 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4608 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4609 	}
       
  4610 
       
  4611 	EAP_ASSERT_ALWAYS(EAP_CORE_PACKET_BUFFER_LENGTH >= (m_eap_header_offset+m_trailer_length));
       
  4612 	u32_t packet_buffer_free = EAP_CORE_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  4613 
       
  4614 	if (m_eap_header_offset+m_MTU < packet_buffer_free)
       
  4615 	{
       
  4616 		packet_buffer_free = m_eap_header_offset+m_MTU;
       
  4617 	}
       
  4618 
       
  4619 	eap_header_wr_c eap_response(
       
  4620 		m_am_tools,
       
  4621 		eap_success_packet.get_data_offset(
       
  4622 			m_eap_header_offset,
       
  4623 			(packet_buffer_free-m_eap_header_offset)),
       
  4624 		(packet_buffer_free-m_eap_header_offset));
       
  4625 
       
  4626 	if (eap_response.get_is_valid() == false)
       
  4627 	{
       
  4628 		EAP_TRACE_ERROR(
       
  4629 			m_am_tools, 
       
  4630 			TRACE_FLAGS_DEFAULT, 
       
  4631 			(EAPL("eap_core_c::send_eap_success(): %s, %s, packet buffer corrupted.\n"),
       
  4632 			 (m_is_client == true) ? "client": "server",
       
  4633 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4634 			 ));
       
  4635 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4636 	}
       
  4637 
       
  4638 	eap_response.reset_header(
       
  4639 		static_cast<u16_t>((packet_buffer_free-m_eap_header_offset)),
       
  4640 		m_use_eap_expanded_type);
       
  4641 	eap_response.set_length(
       
  4642 		static_cast<u16_t>((eap_header_wr_c::get_header_length())),
       
  4643 		m_use_eap_expanded_type);
       
  4644 	eap_response.set_code(eap_code_success);
       
  4645 	eap_response.set_identifier(eap_identifier);
       
  4646 
       
  4647 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4648 
       
  4649 	eap_status_e status = eap_status_process_general_error;
       
  4650 
       
  4651 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4652 
       
  4653 	eap_success_packet.set_data_length(m_eap_header_offset+eap_response.get_header_length());
       
  4654 
       
  4655 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("    send: EAP-success packet"),
       
  4656 		eap_response.get_header_buffer(eap_response.get_length()),
       
  4657 		eap_response.get_length()));
       
  4658 
       
  4659 	status = packet_send(
       
  4660 		send_network_id,
       
  4661 		&eap_success_packet,
       
  4662 		m_eap_header_offset,
       
  4663 		eap_response.get_length(),
       
  4664 		EAP_CORE_PACKET_BUFFER_LENGTH
       
  4665 		);
       
  4666 
       
  4667 	if (status == eap_status_ok)
       
  4668 	{
       
  4669 		// After EAP-Success is sent no re-transmissions must occur.
       
  4670 		cancel_retransmission();
       
  4671 	}
       
  4672 
       
  4673 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4674 
       
  4675 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4676 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4677 }
       
  4678 
       
  4679 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4680 
       
  4681 //--------------------------------------------------
       
  4682 
       
  4683 #if defined(USE_EAP_CORE_SERVER)
       
  4684 
       
  4685 //
       
  4686 EAP_FUNC_EXPORT eap_status_e eap_core_c::send_eap_failure(
       
  4687 	const eap_am_network_id_c * const send_network_id,
       
  4688 	const u8_t eap_identifier)
       
  4689 {
       
  4690 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4691 
       
  4692 	if (m_eap_failure_sent == true)
       
  4693 	{
       
  4694 		EAP_TRACE_ERROR(
       
  4695 			m_am_tools, 
       
  4696 			TRACE_FLAGS_DEFAULT, 
       
  4697 			(EAPL("eap_core_c::send_eap_failure(): %s, %s, EAP-Failure already sent.\n"),
       
  4698 			 (m_is_client == true) ? "client": "server",
       
  4699 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4700 			 ));
       
  4701 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4702 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4703 	}
       
  4704 
       
  4705 	eap_buf_chain_wr_c eap_failure_packet(
       
  4706 		eap_write_buffer, 
       
  4707 		m_am_tools, 
       
  4708 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
  4709 
       
  4710 	if (eap_failure_packet.get_is_valid() == false)
       
  4711 	{
       
  4712 		EAP_TRACE_ERROR(
       
  4713 			m_am_tools, 
       
  4714 			TRACE_FLAGS_DEFAULT, 
       
  4715 			(EAPL("eap_core_c::send_eap_failure(): %s, %s, packet buffer corrupted.\n"),
       
  4716 			 (m_is_client == true) ? "client": "server",
       
  4717 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4718 			 ));
       
  4719 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4720 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4721 	}
       
  4722 
       
  4723 	EAP_ASSERT_ALWAYS(EAP_CORE_PACKET_BUFFER_LENGTH >= (m_eap_header_offset+m_trailer_length));
       
  4724 	u32_t packet_buffer_free = EAP_CORE_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  4725 
       
  4726 	if (m_eap_header_offset+m_MTU < packet_buffer_free)
       
  4727 	{
       
  4728 		packet_buffer_free = m_eap_header_offset+m_MTU;
       
  4729 	}
       
  4730 
       
  4731 	eap_header_wr_c eap_response(
       
  4732 		m_am_tools,
       
  4733 		eap_failure_packet.get_data_offset(
       
  4734 			m_eap_header_offset,
       
  4735 			(packet_buffer_free-m_eap_header_offset)),
       
  4736 		(packet_buffer_free-m_eap_header_offset));
       
  4737 
       
  4738 	if (eap_response.get_is_valid() == false)
       
  4739 	{
       
  4740 		EAP_TRACE_ERROR(
       
  4741 			m_am_tools, 
       
  4742 			TRACE_FLAGS_DEFAULT, 
       
  4743 			(EAPL("eap_core_c::send_eap_failure(): %s, %s, packet buffer corrupted.\n"),
       
  4744 			 (m_is_client == true) ? "client": "server",
       
  4745 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4746 			 ));
       
  4747 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4748 	}
       
  4749 
       
  4750 	eap_response.reset_header(
       
  4751 		static_cast<u16_t>((packet_buffer_free-m_eap_header_offset)),
       
  4752 		m_use_eap_expanded_type);
       
  4753 	eap_response.set_length(
       
  4754 		static_cast<u16_t>((eap_header_wr_c::get_header_length())),
       
  4755 		m_use_eap_expanded_type);
       
  4756 	eap_response.set_code(eap_code_failure);
       
  4757 	eap_response.set_identifier(eap_identifier);
       
  4758 
       
  4759 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4760 
       
  4761 	eap_status_e status = eap_status_process_general_error;
       
  4762 
       
  4763 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4764 
       
  4765 	eap_failure_packet.set_data_length(m_eap_header_offset+eap_response.get_header_length());
       
  4766 
       
  4767 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("    send: EAP-failure packet"),
       
  4768 		eap_response.get_header_buffer(eap_response.get_length()),
       
  4769 		eap_response.get_length()));
       
  4770 
       
  4771 	status = packet_send(
       
  4772 		send_network_id,
       
  4773 		&eap_failure_packet,
       
  4774 		m_eap_header_offset,
       
  4775 		eap_response.get_length(),
       
  4776 		EAP_CORE_PACKET_BUFFER_LENGTH
       
  4777 		);
       
  4778 
       
  4779 	if (status == eap_status_ok)
       
  4780 	{
       
  4781 		m_eap_failure_sent = true;
       
  4782 
       
  4783 		// After EAP-Failure is sent no re-transmissions must occur.
       
  4784 		cancel_retransmission();
       
  4785 	}
       
  4786 
       
  4787 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4788 
       
  4789 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4790 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4791 }
       
  4792 
       
  4793 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4794 
       
  4795 //--------------------------------------------------
       
  4796 
       
  4797 //
       
  4798 EAP_FUNC_EXPORT eap_status_e eap_core_c::send_eap_notification_response(
       
  4799 	const eap_am_network_id_c * const send_network_id,
       
  4800 	const u8_t eap_identifier)
       
  4801 {
       
  4802 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4803 
       
  4804 	eap_buf_chain_wr_c eap_notification_packet(
       
  4805 		eap_write_buffer, 
       
  4806 		m_am_tools, 
       
  4807 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
  4808 
       
  4809 	if (eap_notification_packet.get_is_valid() == false)
       
  4810 	{
       
  4811 		EAP_TRACE_ERROR(
       
  4812 			m_am_tools, 
       
  4813 			TRACE_FLAGS_DEFAULT, 
       
  4814 			(EAPL("eap_core_c::send_eap_notification_response(): ")
       
  4815 			 EAPL("%s, %s, packet buffer corrupted.\n"),
       
  4816 			 (m_is_client == true) ? "client": "server",
       
  4817 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4818 			 ));
       
  4819 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4820 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4821 	}
       
  4822 
       
  4823 	EAP_ASSERT_ALWAYS(EAP_CORE_PACKET_BUFFER_LENGTH >= (m_eap_header_offset+m_trailer_length));
       
  4824 	u32_t packet_buffer_free = EAP_CORE_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  4825 
       
  4826 	if (m_eap_header_offset+m_MTU < packet_buffer_free)
       
  4827 	{
       
  4828 		packet_buffer_free = m_eap_header_offset+m_MTU;
       
  4829 	}
       
  4830 
       
  4831 	eap_header_wr_c eap_response(
       
  4832 		m_am_tools,
       
  4833 		eap_notification_packet.get_data_offset(
       
  4834 			m_eap_header_offset,
       
  4835 			(packet_buffer_free-m_eap_header_offset)),
       
  4836 		(packet_buffer_free-m_eap_header_offset));
       
  4837 
       
  4838 	if (eap_response.get_is_valid() == false)
       
  4839 	{
       
  4840 		EAP_TRACE_ERROR(
       
  4841 			m_am_tools, 
       
  4842 			TRACE_FLAGS_DEFAULT, 
       
  4843 			(EAPL("eap_core_c::send_eap_notification_response(): ")
       
  4844 			 EAPL("%s, %s, packet buffer corrupted.\n"),
       
  4845 			 (m_is_client == true) ? "client": "server",
       
  4846 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4847 			 ));
       
  4848 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4849 	}
       
  4850 
       
  4851 	eap_response.reset_header(
       
  4852 		static_cast<u16_t>((packet_buffer_free-m_eap_header_offset)),
       
  4853 		m_use_eap_expanded_type);
       
  4854 	eap_response.set_length(
       
  4855 		static_cast<u16_t>((eap_header_base_c::get_header_length()+1u)),
       
  4856 		m_use_eap_expanded_type);
       
  4857 	eap_response.set_code(eap_code_response);
       
  4858 	eap_response.set_identifier(eap_identifier);
       
  4859 	eap_response.set_type(eap_type_notification, m_use_eap_expanded_type);
       
  4860 	
       
  4861 
       
  4862 	eap_status_e status = eap_status_process_general_error;
       
  4863 
       
  4864 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4865 
       
  4866 	eap_notification_packet.set_data_length(
       
  4867 		m_eap_header_offset+eap_response.get_header_length()+1u);
       
  4868 
       
  4869 	EAP_TRACE_DATA_DEBUG(
       
  4870 		m_am_tools,
       
  4871 		TRACE_FLAGS_DEFAULT,
       
  4872 		(EAPL("    send: EAP-Response/Notification packet"),
       
  4873 		 eap_response.get_header_buffer(eap_response.get_length()),
       
  4874 		 eap_response.get_length()));
       
  4875 	
       
  4876 	status = packet_send(
       
  4877 		send_network_id,
       
  4878 		&eap_notification_packet,
       
  4879 		m_eap_header_offset,
       
  4880 		eap_response.get_length(),
       
  4881 		EAP_CORE_PACKET_BUFFER_LENGTH
       
  4882 		);
       
  4883 
       
  4884 	if (status == eap_status_ok)
       
  4885 	{
       
  4886 		// After EAP-Notification is sent no re-transmissions must occur.
       
  4887 		cancel_retransmission();
       
  4888 	}
       
  4889 
       
  4890 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4891 
       
  4892 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4893 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4894 }
       
  4895 
       
  4896 
       
  4897 //--------------------------------------------------
       
  4898 
       
  4899 //
       
  4900 EAP_FUNC_EXPORT eap_status_e eap_core_c::create_eap_identity_response(
       
  4901 	eap_buf_chain_wr_c * const response_packet,
       
  4902 	const eap_variable_data_c * const identity,
       
  4903 	const u8_t eap_identifier
       
  4904 	)
       
  4905 {
       
  4906 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4907 
       
  4908 	if (identity == 0
       
  4909 		|| identity->get_is_valid_data() == false)
       
  4910 	{
       
  4911 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4912 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4913 	}
       
  4914 
       
  4915 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4916 
       
  4917 	if (response_packet == 0
       
  4918 		|| response_packet->get_is_valid() == false)
       
  4919 	{
       
  4920 		EAP_TRACE_ERROR(
       
  4921 			m_am_tools, 
       
  4922 			TRACE_FLAGS_DEFAULT, 
       
  4923 			(EAPL("packet buffer corrupted: %s, %s\n"),
       
  4924 			 (m_is_client == true) ? "client": "server",
       
  4925 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4926 			 ));
       
  4927 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4928 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4929 	}
       
  4930 
       
  4931 	EAP_ASSERT_ALWAYS(EAP_CORE_PACKET_BUFFER_LENGTH >= (m_eap_header_offset+m_trailer_length));
       
  4932 	u32_t packet_buffer_free = EAP_CORE_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  4933 	u32_t packet_buffer_offset = 0u;
       
  4934 
       
  4935 	if (m_eap_header_offset+m_MTU < packet_buffer_free)
       
  4936 	{
       
  4937 		packet_buffer_free = m_eap_header_offset+m_MTU;
       
  4938 	}
       
  4939 
       
  4940 	eap_header_wr_c eap_response(
       
  4941 		m_am_tools,
       
  4942 		response_packet->get_data_offset(
       
  4943 			m_eap_header_offset,
       
  4944 			(EAP_CORE_PACKET_BUFFER_LENGTH-(m_eap_header_offset+m_trailer_length))),
       
  4945 		EAP_CORE_PACKET_BUFFER_LENGTH-(m_eap_header_offset+m_trailer_length));
       
  4946 
       
  4947 	if (eap_response.get_is_valid() == false)
       
  4948 	{
       
  4949 		EAP_TRACE_ERROR(
       
  4950 			m_am_tools, 
       
  4951 			TRACE_FLAGS_DEFAULT, 
       
  4952 			(EAPL("send_eap_identity_response: %s, %s, packet buffer corrupted.\n"),
       
  4953 			 (m_is_client == true) ? "client": "server",
       
  4954 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4955 			 ));
       
  4956 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4957 	}
       
  4958 
       
  4959 	eap_response.reset_header(
       
  4960 		static_cast<u16_t>((packet_buffer_free-m_eap_header_offset)),
       
  4961 		m_use_eap_expanded_type);
       
  4962 
       
  4963 	eap_response.set_length(
       
  4964 		static_cast<u16_t>((packet_buffer_free-m_eap_header_offset)),
       
  4965 		m_use_eap_expanded_type);
       
  4966 	eap_response.set_code(eap_code_response);
       
  4967 	eap_response.set_identifier(eap_identifier);
       
  4968 	eap_response.set_type(eap_type_identity, m_use_eap_expanded_type);
       
  4969 
       
  4970 	packet_buffer_offset += eap_response.get_header_length();
       
  4971 
       
  4972 	u8_t * const target_nai = eap_response.get_type_data(
       
  4973 		identity->get_data_length());
       
  4974 	if (target_nai == 0)
       
  4975 	{
       
  4976 		EAP_TRACE_ERROR(
       
  4977 			m_am_tools, 
       
  4978 			TRACE_FLAGS_DEFAULT, 
       
  4979 			(EAPL("send_eap_identity_response: %s, %s, too long EAP-Identity.\n"),
       
  4980 			 (m_is_client == true) ? "client": "server",
       
  4981 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  4982 			 ));
       
  4983 
       
  4984 		EAP_TRACE_DATA_DEBUG(
       
  4985 			m_am_tools,
       
  4986 			TRACE_FLAGS_DEFAULT,
       
  4987 			(EAPL("Identity"),
       
  4988 			 identity->get_data(identity->get_data_length()),
       
  4989 			 identity->get_data_length()));
       
  4990 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4991 	}
       
  4992 
       
  4993 	m_am_tools->memmove(
       
  4994 		target_nai,
       
  4995 		identity->get_data(identity->get_data_length()), 
       
  4996 		identity->get_data_length());
       
  4997 
       
  4998 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4999 
       
  5000 	eap_response.set_type_data_length(
       
  5001 		static_cast<u16_t>(identity->get_data_length()),
       
  5002 		m_use_eap_expanded_type);
       
  5003 
       
  5004 	response_packet->set_data_length(m_eap_header_offset+eap_response.get_length());
       
  5005 
       
  5006 	EAP_TRACE_DATA_DEBUG(
       
  5007 		m_am_tools,
       
  5008 		TRACE_FLAGS_DEFAULT,
       
  5009 		(EAPL("send EAP-identity NAI"),
       
  5010 		 eap_response.get_type_data(eap_response.get_type_data_length()),
       
  5011 		 eap_response.get_type_data_length()));
       
  5012 
       
  5013 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5014 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5015 }
       
  5016 
       
  5017 //--------------------------------------------------
       
  5018 
       
  5019 //
       
  5020 EAP_FUNC_EXPORT eap_status_e eap_core_c::send_eap_identity_response(
       
  5021 	const eap_am_network_id_c * const send_network_id,
       
  5022 	const eap_variable_data_c * const identity,
       
  5023 	const u8_t eap_identifier
       
  5024 	)
       
  5025 {
       
  5026 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5027 
       
  5028 	eap_status_e status = eap_status_process_general_error;
       
  5029 
       
  5030 	if (send_network_id == 0
       
  5031 		|| identity == 0)
       
  5032 	{
       
  5033 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5034 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  5035 	}
       
  5036 
       
  5037 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  5038 
       
  5039 	eap_buf_chain_wr_c response_packet(
       
  5040 		eap_write_buffer, 
       
  5041 		m_am_tools, 
       
  5042 		EAP_CORE_PACKET_BUFFER_LENGTH);
       
  5043 
       
  5044 	if (response_packet.get_is_valid() == false)
       
  5045 	{
       
  5046 		EAP_TRACE_ERROR(
       
  5047 			m_am_tools, 
       
  5048 			TRACE_FLAGS_DEFAULT, 
       
  5049 			(EAPL("packet buffer corrupted: %s, %s.\n"),
       
  5050 			 (m_is_client == true) ? "client": "server",
       
  5051 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  5052 			 ));
       
  5053 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5054 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5055 	}
       
  5056 
       
  5057 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  5058 
       
  5059 	// Get add possible NAI decoration and 
       
  5060 	// extra routing info to identity
       
  5061 
       
  5062 	eap_variable_data_c local_identity(m_am_tools);
       
  5063 	status = local_identity.set_copy_of_buffer(identity);
       
  5064 	if (status != eap_status_ok)
       
  5065 	{
       
  5066 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5067 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5068 	}
       
  5069 
       
  5070 	status = set_eap_identity_routing_info_and_nai_decoration(&local_identity);
       
  5071 	if (status != eap_status_ok)
       
  5072 	{
       
  5073 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5074 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5075 	}
       
  5076 
       
  5077 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  5078 
       
  5079 	status = create_eap_identity_response(
       
  5080 		&response_packet,
       
  5081 		&local_identity,
       
  5082 		eap_identifier);
       
  5083 	if (status != eap_status_ok)
       
  5084 	{
       
  5085 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5086 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5087 	}
       
  5088 
       
  5089 	eap_header_wr_c eap_response(
       
  5090 		m_am_tools,
       
  5091 		response_packet.get_data_offset(
       
  5092 			m_eap_header_offset,
       
  5093 			(response_packet.get_buffer_length()-(m_eap_header_offset+m_trailer_length))),
       
  5094 		response_packet.get_buffer_length()-(m_eap_header_offset+m_trailer_length));
       
  5095 	if (eap_response.get_is_valid() == false)
       
  5096 	{
       
  5097 		EAP_TRACE_ERROR(
       
  5098 			m_am_tools, 
       
  5099 			TRACE_FLAGS_DEFAULT, 
       
  5100 			(EAPL("send_eap_identity_response: %s, %s, packet buffer corrupted.\n"),
       
  5101 			 (m_is_client == true) ? "client": "server",
       
  5102 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most"
       
  5103 			 ));
       
  5104 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  5105 	}
       
  5106 
       
  5107 	status = packet_send(
       
  5108 		send_network_id,
       
  5109 		&response_packet,
       
  5110 		m_eap_header_offset,
       
  5111 		eap_response.get_length(),
       
  5112 		response_packet.get_buffer_length());
       
  5113 	if (status != eap_status_ok)
       
  5114 	{
       
  5115 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5116 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5117 	}
       
  5118 
       
  5119 
       
  5120 #if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  5121 
       
  5122 	if (m_is_tunneled_eap == false
       
  5123 		&& m_is_client_role == true)
       
  5124 	{
       
  5125 		status = cancel_wait_eap_request_type_timeout();
       
  5126 		if (status != eap_status_ok)
       
  5127 		{
       
  5128 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5129 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5130 		}
       
  5131 
       
  5132 		status = set_wait_eap_request_type_timeout();
       
  5133 	}
       
  5134 
       
  5135 #endif //#if defined(USE_EAP_CORE_WAIT_REQUEST_TYPE_TIMER)
       
  5136 
       
  5137 
       
  5138 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5139 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5140 }
       
  5141 
       
  5142 //--------------------------------------------------
       
  5143 
       
  5144 //
       
  5145 eap_status_e eap_core_c::set_eap_identity_routing_info_and_nai_decoration(
       
  5146 	eap_variable_data_c * const identity)
       
  5147 {
       
  5148 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5149 
       
  5150 	if (identity == 0
       
  5151 		|| identity->get_is_valid_data() == false)
       
  5152 	{
       
  5153 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5154 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5155 	}
       
  5156 
       
  5157 	bool routing_info_available(true);
       
  5158 	bool nai_decoration_available(true);
       
  5159 
       
  5160 	eap_status_e status(eap_status_process_general_error);
       
  5161 
       
  5162 	// read routing info from AM
       
  5163 	eap_variable_data_c routing_info(m_am_tools);
       
  5164 	status = read_configure(
       
  5165 		cf_str_EAP_outer_identity_routing.get_field(),
       
  5166 		&routing_info);
       
  5167 	if (status != eap_status_ok 
       
  5168 		|| routing_info.get_is_valid_data() == false 
       
  5169 		|| routing_info.get_data_length() == 0)
       
  5170 	{
       
  5171 		routing_info_available = false;
       
  5172 	}
       
  5173 
       
  5174 	// read NAI decoration from AM
       
  5175 	eap_variable_data_c nai_decoration(m_am_tools);
       
  5176 	status = read_configure(
       
  5177 		cf_str_EAP_outer_identity_decoration.get_field(),
       
  5178 		&nai_decoration);
       
  5179 	if (status != eap_status_ok 
       
  5180 		|| nai_decoration.get_is_valid_data() == false 
       
  5181 		|| nai_decoration.get_data_length() == 0)
       
  5182 	{
       
  5183 		nai_decoration_available = false;
       
  5184 	}
       
  5185 
       
  5186 	// nothing to be added (which is ok)
       
  5187 	if(routing_info_available == false 
       
  5188 		&& nai_decoration_available == false) 
       
  5189 	{
       
  5190 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5191 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5192 	}
       
  5193 
       
  5194 	eap_variable_data_c username(m_am_tools);
       
  5195 	eap_variable_data_c home_realm(m_am_tools);
       
  5196 
       
  5197 	// get username and home realm from the current NAI
       
  5198 	status = m_am_tools->parse_nai(
       
  5199 		identity,
       
  5200 		&username,
       
  5201 		&home_realm);
       
  5202 	if (status != eap_status_ok)
       
  5203 	{
       
  5204 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5205 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5206 	}
       
  5207 
       
  5208 	// username must be present
       
  5209 	if (username.get_is_valid_data() == false
       
  5210 		/* || home_realm.get_is_valid_data() == false */)
       
  5211 	{
       
  5212 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5213 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5214 	}
       
  5215 
       
  5216 	// original NAI can be cleared,
       
  5217 	// the new one is constructed to the same place
       
  5218 	identity->reset();
       
  5219 
       
  5220 	// routing_info contains a string in format 
       
  5221 	// "RoutingRealm1!RoutingRealm2!RoutingRealm3"
       
  5222 	// in which RoutingRealm3 is replaced with the home
       
  5223 	// realm and RoutingRealm1 is appended after @-sign in NAI
       
  5224 	if(routing_info_available == true) 
       
  5225 	{
       
  5226 		// this points to the last byte of routing_info
       
  5227 		const u8_t* const p_last = 
       
  5228 			routing_info.get_data() + 
       
  5229 			(routing_info.get_data_length() - 1);
       
  5230 
       
  5231 		// first and last characters cannot be !-signs
       
  5232 		if(*p_last == EAP_NAI_ROUTING_REALM_SEPARATOR[0]
       
  5233 			|| *(routing_info.get_data()) == EAP_NAI_ROUTING_REALM_SEPARATOR[0])
       
  5234 		{
       
  5235 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5236 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5237 		}
       
  5238 
       
  5239 		// find first !-sign
       
  5240 		const u8_t *separator = reinterpret_cast<const u8_t *>(
       
  5241 			m_am_tools->memchr(
       
  5242 				routing_info.get_data(),
       
  5243 				EAP_NAI_ROUTING_REALM_SEPARATOR[0],
       
  5244 				routing_info.get_data_length())
       
  5245 			);
       
  5246 
       
  5247 		// !-sign found, more than one realm present
       
  5248 		// (the sign is not first or last character)
       
  5249 		if (separator != 0)
       
  5250 		{
       
  5251 			// others except the first realm are put in front
       
  5252 			status = identity->add_data(
       
  5253 				separator + 1, 
       
  5254 				p_last - separator);
       
  5255 			if (status != eap_status_ok)
       
  5256 			{
       
  5257 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5258 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  5259 			}
       
  5260 
       
  5261 			// add !-sign
       
  5262 			status = identity->add_data(EAP_NAI_ROUTING_REALM_SEPARATOR, 1);
       
  5263 			if (status != eap_status_ok)
       
  5264 			{
       
  5265 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5266 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  5267 			}
       
  5268 
       
  5269 		}
       
  5270 
       
  5271 		// add home realm if it existed
       
  5272 		if(home_realm.get_is_valid_data() == true)
       
  5273 		{
       
  5274 			status = identity->add_data(
       
  5275 				home_realm.get_data(), 
       
  5276 				home_realm.get_data_length());
       
  5277 			if (status != eap_status_ok)
       
  5278 			{
       
  5279 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5280 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  5281 			}
       
  5282 
       
  5283 			// add !-sign
       
  5284 			status = identity->add_data(EAP_NAI_ROUTING_REALM_SEPARATOR, 1);
       
  5285 			if (status != eap_status_ok)
       
  5286 			{
       
  5287 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5288 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  5289 			}
       
  5290 		}
       
  5291 
       
  5292 		// store the first realm of routing info here
       
  5293 		home_realm.reset();
       
  5294 
       
  5295 		// more than one realm in routing info
       
  5296 		if (separator != 0) 
       
  5297 		{
       
  5298 			status = home_realm.add_data(
       
  5299 				routing_info.get_data(), 
       
  5300 				separator - routing_info.get_data()
       
  5301 				);
       
  5302 		}
       
  5303 		// only one realm in routing info
       
  5304 		else
       
  5305 		{
       
  5306 			status = home_realm.add_data(
       
  5307 				routing_info.get_data(), 
       
  5308 				routing_info.get_data_length());
       
  5309 		}
       
  5310 
       
  5311 		if (status != eap_status_ok)
       
  5312 		{
       
  5313 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5314 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5315 		}
       
  5316 	}
       
  5317 
       
  5318 	// nai_decoration contains a string which is placed 
       
  5319 	// in front of the username in NAI
       
  5320 	if(nai_decoration_available == true) 
       
  5321 	{
       
  5322 		status = identity->add_data(nai_decoration.get_data(), nai_decoration.get_data_length());
       
  5323 		if (status != eap_status_ok)
       
  5324 		{
       
  5325 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5326 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5327 		}
       
  5328 	}
       
  5329 
       
  5330 	status = identity->add_data(username.get_data(), username.get_data_length());
       
  5331 	if (status != eap_status_ok)
       
  5332 	{
       
  5333 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5334 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5335 	}
       
  5336 	
       
  5337 	// add realm if it exists
       
  5338         if (home_realm.get_is_valid_data() == true) {
       
  5339 	  // add @-sign
       
  5340 	  status = identity->add_data(EAP_NAI_AT_CHARACTER, 1);
       
  5341 	  if (status != eap_status_ok)
       
  5342 	    {
       
  5343 	      EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5344 	      return EAP_STATUS_RETURN(m_am_tools, status);
       
  5345 	    }
       
  5346 	  
       
  5347 	  status = identity->add_data(home_realm.get_data(), home_realm.get_data_length());
       
  5348 	}
       
  5349 	
       
  5350 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5351 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5352 
       
  5353 }
       
  5354 
       
  5355 //--------------------------------------------------
       
  5356 
       
  5357 //
       
  5358 EAP_FUNC_EXPORT eap_status_e eap_core_c::complete_eap_identity_query(
       
  5359 	const eap_am_network_id_c * const send_network_id,
       
  5360 	const eap_variable_data_c * const identity,
       
  5361 	const u8_t /*eap_identifier*/) // Remove eap_identifier parameter.
       
  5362 {
       
  5363 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5364 	eap_status_e status(eap_status_illegal_eap_identity);
       
  5365 
       
  5366 	if (identity != 0)
       
  5367 	{
       
  5368 		status = m_eap_identity.set_copy_of_buffer(identity);
       
  5369 		if (status != eap_status_ok)
       
  5370 		{
       
  5371 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5372 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5373 		}
       
  5374 			
       
  5375 		status = send_eap_identity_response(
       
  5376 			send_network_id,
       
  5377 			identity,
       
  5378 			m_eap_identity_request_identifier_client); // Uses the EAP-Identifier from the latest EAP-Request/Identity.
       
  5379 	}
       
  5380 
       
  5381 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5382 }
       
  5383 
       
  5384 //--------------------------------------------------
       
  5385 
       
  5386 //
       
  5387 EAP_FUNC_EXPORT eap_status_e eap_core_c::get_saved_eap_identity(
       
  5388 	eap_variable_data_c * const identity)
       
  5389 {
       
  5390 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5391 
       
  5392 	eap_status_e status = eap_status_illegal_eap_identity;
       
  5393 
       
  5394 	if (m_eap_identity.get_is_valid_data() == true)
       
  5395 	{
       
  5396 		status = identity->set_copy_of_buffer(&m_eap_identity);
       
  5397 	}
       
  5398 	else
       
  5399 	{
       
  5400 		EAP_TRACE_DEBUG(
       
  5401 			m_am_tools,
       
  5402 			TRACE_FLAGS_DEFAULT,
       
  5403 			(EAPL("WARNING: %s, %s, EAP-identity is unknown: current EAP-type 0x%08x\n"),
       
  5404 			 (m_is_client == true) ? "client": "server",
       
  5405 			 (m_is_tunneled_eap == true) ? "tunneled": "outer most",
       
  5406 			 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5407 	}
       
  5408 
       
  5409 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5410 	return EAP_STATUS_RETURN_WARNING(m_am_tools, status);
       
  5411 }
       
  5412 
       
  5413 //--------------------------------------------------
       
  5414 
       
  5415 //
       
  5416 EAP_FUNC_EXPORT eap_status_e eap_core_c::set_session_timeout(
       
  5417 	const u32_t session_timeout_ms)
       
  5418 {
       
  5419 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5420 
       
  5421 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5422 
       
  5423 	eap_status_e status = initialize_session_timeout(session_timeout_ms);
       
  5424 	if (status != eap_status_ok)
       
  5425 	{
       
  5426 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5427 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5428 	}
       
  5429 
       
  5430 	if (m_is_tunneled_eap == true)
       
  5431 	{
       
  5432 		status = m_partner->set_session_timeout(session_timeout_ms);
       
  5433 		if (status != eap_status_ok)
       
  5434 		{
       
  5435 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5436 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5437 		}
       
  5438 	}
       
  5439 
       
  5440 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5441 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5442 }
       
  5443 
       
  5444 //--------------------------------------------------
       
  5445 
       
  5446 //
       
  5447 EAP_FUNC_EXPORT eap_status_e eap_core_c::set_timer(
       
  5448 	abs_eap_base_timer_c * const p_initializer, 
       
  5449 	const u32_t p_id, 
       
  5450 	void * const p_data,
       
  5451 	const u32_t p_time_ms)
       
  5452 {
       
  5453 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5454 
       
  5455 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5456 
       
  5457 	const eap_status_e status = m_partner->set_timer(
       
  5458 		p_initializer, 
       
  5459 		p_id, 
       
  5460 		p_data,
       
  5461 		p_time_ms);
       
  5462 
       
  5463 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5464 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5465 }
       
  5466 
       
  5467 //--------------------------------------------------
       
  5468 
       
  5469 //
       
  5470 EAP_FUNC_EXPORT eap_status_e eap_core_c::cancel_timer(
       
  5471 	abs_eap_base_timer_c * const p_initializer, 
       
  5472 	const u32_t p_id)
       
  5473 {
       
  5474 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5475 
       
  5476 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5477 
       
  5478 	const eap_status_e status = m_partner->cancel_timer(
       
  5479 		p_initializer, 
       
  5480 		p_id);
       
  5481 
       
  5482 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5483 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5484 }
       
  5485 
       
  5486 //--------------------------------------------------
       
  5487 
       
  5488 //
       
  5489 EAP_FUNC_EXPORT eap_status_e eap_core_c::cancel_all_timers()
       
  5490 {
       
  5491 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5492 
       
  5493 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5494 
       
  5495 	const eap_status_e status = m_partner->cancel_all_timers();
       
  5496 
       
  5497 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5498 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5499 }
       
  5500 
       
  5501 //--------------------------------------------------
       
  5502 
       
  5503 EAP_FUNC_EXPORT eap_status_e eap_core_c::set_authentication_role(const bool when_true_set_client)
       
  5504 {
       
  5505 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5506 
       
  5507 	cancel_retransmission();
       
  5508 
       
  5509 	cancel_eap_failure_timeout();
       
  5510 
       
  5511 	m_is_client_role = when_true_set_client;
       
  5512 
       
  5513 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5514 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5515 }
       
  5516 
       
  5517 //--------------------------------------------------
       
  5518 
       
  5519 EAP_FUNC_EXPORT eap_status_e eap_core_c::add_rogue_ap(
       
  5520 	eap_array_c<eap_rogue_ap_entry_c> & rogue_ap_list)
       
  5521 {
       
  5522 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5523 
       
  5524 	const eap_status_e status = m_partner->add_rogue_ap(rogue_ap_list);
       
  5525 
       
  5526 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5527 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5528 }
       
  5529 
       
  5530 //--------------------------------------------------
       
  5531 
       
  5532 EAP_FUNC_EXPORT bool eap_core_c::get_is_tunneled_eap() const
       
  5533 {
       
  5534 	return m_is_tunneled_eap;
       
  5535 }
       
  5536 
       
  5537 //--------------------------------------------------
       
  5538 //--------------------------------------------------
       
  5539 
       
  5540 
       
  5541 
       
  5542 // End.