eapol/eapol_framework/eapol_common/type/diameter/src/eap_diameter_avp_header.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/type/diameter/src/eap_diameter_avp_header.cpp	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,582 @@
+/*
+* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  EAP and WLAN authentication protocols.
+*
+*/
+
+
+// This is enumeration of EAPOL source code.
+#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+	#undef EAP_FILE_NUMBER_ENUM
+	#define EAP_FILE_NUMBER_ENUM 73 
+	#undef EAP_FILE_NUMBER_DATE 
+	#define EAP_FILE_NUMBER_DATE 1127594498 
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+
+
+#include "eap_diameter_avp_header.h"
+
+/** @file */
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns length of the required padding.
+ */
+u32_t eap_diameter_avp_header_c::get_padding_length() const
+{
+	// NOTE AVP is padded always to multiple of 4 octets.
+	u32_t avp_length = get_length();
+	u32_t remainder = avp_length % 4ul;
+	if (remainder != 0ul)
+	{
+		return 4ul - remainder;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * The destructor of the eap_diameter_avp_header_c class does nothing.
+ */
+eap_diameter_avp_header_c::~eap_diameter_avp_header_c()
+{
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * The constructor of the eap_diameter_avp_header_c class simply initializes the attributes.
+ */
+eap_diameter_avp_header_c::eap_diameter_avp_header_c(
+	abs_eap_am_tools_c * const tools,
+	void * const header_begin,
+	const u32_t header_buffer_length)
+	: eap_general_header_base_c(tools, header_begin, header_buffer_length)
+	, m_am_tools(tools)
+{
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the AVP Code.
+ */
+eap_diameter_avp_code_c eap_diameter_avp_header_c::get_avp_code() const
+{
+	const u8_t * const code_data = get_header_offset(m_avp_code_offset, sizeof(u32_t));
+	if (code_data  != 0)
+	{
+		const u32_t avp_code = eap_read_u32_t_network_order(code_data, sizeof(u32_t));
+
+		eap_diameter_vendor_id_e vendor_id(eap_diameter_vendor_id_of_ietf);
+
+		if (get_avp_flag_vendor_specific() == true)
+		{
+			// We have vendor specific AVP code.
+			// This reads the vendor ID.
+			const u8_t * const vendor_id_data = get_header_offset(m_vendor_id_or_data_offset, sizeof(u32_t));
+			if (vendor_id_data  != 0)
+			{
+				vendor_id = static_cast<eap_diameter_vendor_id_e>(eap_read_u32_t_network_order(vendor_id_data, sizeof(u32_t)));
+			}
+			else
+			{
+				return eap_diameter_avp_code_none;
+			}
+		}
+
+		eap_diameter_avp_code_c vendor_specific_code(vendor_id, avp_code);
+
+		return vendor_specific_code;
+	}
+	else
+	{
+		return eap_diameter_avp_code_none;
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the AVP vendor specific flag.
+ */
+bool eap_diameter_avp_header_c::get_avp_flag_vendor_specific() const
+{
+	const u8_t * const flags = get_header_offset(m_flags_offset, sizeof(u8_t));
+	if (flags != 0)
+	{
+		if (((*flags) & m_flag_mask_vendor_specific_avp) != 0)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the AVP mandatory flag.
+ */
+bool eap_diameter_avp_header_c::get_avp_flag_mandatory_avp() const
+{
+	const u8_t * const flags = get_header_offset(m_flags_offset, sizeof(u8_t));
+	if (flags != 0)
+	{
+		if (((*flags) & m_flag_mask_mandatory_avp) != 0)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the AVP reserved flags.
+ */
+u8_t eap_diameter_avp_header_c::get_avp_flags_reserved() const
+{
+	const u8_t * const flags = get_header_offset(m_flags_offset, sizeof(u8_t));
+	if (flags != 0)
+	{
+		return static_cast<u8_t>((*flags) & m_flag_mask_reserved_avp);
+	}
+	
+	return 0xff;
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the length of AVP (header+data).
+ */
+u32_t eap_diameter_avp_header_c::get_length() const
+{
+	return get_header_length() + get_data_length();
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the length of AVP data.
+ */
+u32_t eap_diameter_avp_header_c::get_data_length() const
+{
+	const u8_t * const length_data = get_header_offset(m_length_offset, 3ul*sizeof(u8_t));
+	if (length_data != 0)
+	{
+		u32_t header_and_data_length = eap_read_u24_t_network_order(length_data, 3ul*sizeof(u8_t));
+		if (header_and_data_length > get_header_length())
+		{
+			return header_and_data_length - get_header_length();
+		}
+	}
+	return 0ul;
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the header length of AVP.
+ */
+u32_t eap_diameter_avp_header_c::get_header_length(const bool include_vendor_specific)
+{
+	if (include_vendor_specific == true)
+	{
+		return m_data_with_vendor_id_offset;
+	}
+	else
+	{
+		return m_vendor_id_or_data_offset;
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns the header length of AVP.
+ */
+u32_t eap_diameter_avp_header_c::get_header_length() const
+{
+	return get_header_length(get_avp_flag_vendor_specific());
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns pointer to the offset of data of AVP.
+ * @param offset is the offset of queried data in bytes.
+ * @param contignuous_bytes is the length of queried data in bytes.
+ */
+u8_t * eap_diameter_avp_header_c::get_data_offset(const u32_t offset, const u32_t contignuous_bytes) const
+{
+	u32_t data_length = get_header_buffer_length() - get_header_length();
+
+	if (data_length >= offset+contignuous_bytes)
+	{
+		u8_t * data = 0;
+		
+		if (get_avp_flag_vendor_specific() == true)
+		{
+			data = get_header_offset(m_data_with_vendor_id_offset, offset+contignuous_bytes);
+		}
+		else
+		{
+			data = get_header_offset(m_vendor_id_or_data_offset, offset+contignuous_bytes);
+		}
+		
+		if (data != 0)
+		{
+			return &data[offset];
+		}
+		else
+		{
+			return 0;
+		}
+	}
+	else
+	{
+		EAP_ASSERT_ALWAYS(data_length >= offset+contignuous_bytes);
+	}
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns pointer to the offset of data of AVP.
+ * @param contignuous_bytes is the length of queried data in bytes.
+ */
+u8_t * eap_diameter_avp_header_c::get_data(const u32_t contignuous_bytes) const
+{
+	return get_data_offset(0u, contignuous_bytes);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function return pointer to the next AVP header in the same buffer.
+ */
+u8_t * eap_diameter_avp_header_c::get_next_header() const
+{
+	// NOTE AVP is padded always to multiple of 4 octets.
+	u32_t data_length = get_header_buffer_length() - get_header_length();
+	u32_t avp_data_length = get_data_length();
+	u32_t padding_length = get_padding_length();
+	u32_t required_length = avp_data_length+padding_length+EAP_DIAMETER_AVP_MINIMUM_HEADER_LENGTH;
+	
+	if (data_length >= required_length)
+	{
+		return get_data_offset(avp_data_length+padding_length, EAP_DIAMETER_AVP_MINIMUM_HEADER_LENGTH);
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function checks the header is valid.
+ */
+eap_status_e eap_diameter_avp_header_c::check_header() const
+{
+	if (get_avp_code() != eap_diameter_avp_code_eap_message)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
+	}
+	else if (get_avp_flags_reserved() != 0)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
+	}
+	else if (get_avp_flag_vendor_specific() == true
+			 && get_header_buffer_length() < m_data_with_vendor_id_offset)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
+	}
+	else if (get_avp_flag_vendor_specific() == false
+			 && get_header_buffer_length() < m_vendor_id_or_data_offset)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
+	}
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function returns debug strings of the AVP Code.
+ */
+eap_const_string eap_diameter_avp_header_c::get_avp_code_string() const
+{
+
+#if defined(USE_EAP_TRACE_STRINGS)
+	const eap_diameter_avp_code_c code = get_avp_code();
+
+	EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_none)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_user_name)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_user_password)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_chap_password)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_nas_ip_address)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_nas_port)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_service_type)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_protocol)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_ip_address)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_ip_netmask)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_routing)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_filter_id)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_mtu)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_compression)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_ip_host)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_service)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_tcp_port)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_reply_message)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_callback_number)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_callback_id)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_route)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_ipx_network)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_state)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_class)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_vendor_specific)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_session_timeout)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_idle_timeout)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_termination_action)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_called_station_id)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_calling_station_id)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_nas_identifier)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_proxy_state)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_lat_service)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_lat_node)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_lat_group)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_appletalk_link)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_appletalk_network)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_framed_appletalk_zone)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_chap_challenge)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_nas_port_type)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_port_limit)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_login_lat_port)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_eap_message)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_message_authenticator)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_avp_code_eap_message)
+#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
+	else EAP_IF_RETURN_STRING(code, eap_diameter_vendor_code_of_microsoft_ms_chap_error.get_code())
+	else EAP_IF_RETURN_STRING(code, eap_diameter_vendor_code_of_microsoft_ms_chap_nt_enc_pw.get_code())
+	else EAP_IF_RETURN_STRING(code, eap_diameter_vendor_code_of_microsoft_ms_chap_challenge.get_code())
+	else EAP_IF_RETURN_STRING(code, eap_diameter_vendor_code_of_microsoft_ms_chap2_response.get_code())
+	else EAP_IF_RETURN_STRING(code, eap_diameter_vendor_code_of_microsoft_ms_chap2_success.get_code())
+	else EAP_IF_RETURN_STRING(code, eap_diameter_vendor_code_of_microsoft_ms_chap2_cpw.get_code())
+#endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
+	else
+#endif // #if defined(USE_EAP_TRACE_STRINGS)
+	{
+		return EAPL("Unknown AVP code");
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function sets the AVP Code.
+ */
+eap_status_e eap_diameter_avp_header_c::set_avp_code(const eap_diameter_avp_code_c code)
+{
+	eap_status_e status(eap_status_process_general_error);
+
+	{
+		u8_t * const code_data = get_header_offset(m_avp_code_offset, sizeof(u32_t));
+		
+		if (code_data == 0)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = eap_write_u32_t_network_order(
+				code_data,
+				sizeof(u32_t),
+				code.get_vendor_code());
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	if (code.get_vendor_id() != eap_diameter_vendor_id_of_ietf)
+	{
+		// We have vendor specific AVP code.
+		// This writes the vendor ID.
+
+		status = set_avp_flag_vendor_specific(true);
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		u8_t * const vendor_id_data = get_header_offset(m_vendor_id_or_data_offset, sizeof(u32_t));
+		
+		if (vendor_id_data == 0)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = eap_write_u32_t_network_order(
+				vendor_id_data,
+				sizeof(u32_t),
+				code.get_vendor_id());
+		if (status != eap_status_ok)
+		{
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function sets the AVP vendor specific flag.
+ */
+eap_status_e eap_diameter_avp_header_c::set_avp_flag_vendor_specific(
+	const bool vendor_specific)
+{
+	u8_t * const flags = get_header_offset(m_flags_offset, sizeof(u8_t));
+	if (flags != 0)
+	{
+		if (vendor_specific == true)
+		{
+			*flags = static_cast<u8_t>((*flags) | m_flag_mask_vendor_specific_avp);
+		}
+		else
+		{
+			*flags = static_cast<u8_t>((*flags) & ~m_flag_mask_vendor_specific_avp);
+		}
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+	
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function sets the AVP mandatory flag.
+ */
+eap_status_e eap_diameter_avp_header_c::set_avp_flag_mandatory_avp(const bool mandatory)
+{
+	u8_t * const flags = get_header_offset(m_flags_offset, sizeof(u8_t));
+	if (flags != 0)
+	{
+		if (mandatory == true)
+		{
+			*flags = static_cast<u8_t>((*flags) | m_flag_mask_mandatory_avp);
+		}
+		else
+		{
+			*flags = static_cast<u8_t>((*flags) & ~m_flag_mask_mandatory_avp);
+		}
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+	
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function sets the AVP mandatory flag.
+ */
+eap_status_e eap_diameter_avp_header_c::set_avp_flags_reserved()
+{
+	u8_t * const flags = get_header_offset(m_flags_offset, sizeof(u8_t));
+	if (flags != 0)
+	{
+		*flags = static_cast<u8_t>(((*flags) & ~m_flag_mask_reserved_avp) | 0ul);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+	
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function sets the AVP data length.
+ */
+eap_status_e eap_diameter_avp_header_c::set_data_length(const u32_t p_length)
+{
+	u8_t * const length_data = get_header_offset(m_length_offset, 3ul*sizeof(u8_t));
+	if (length_data != 0)
+	{
+		return EAP_STATUS_RETURN(
+			m_am_tools,
+			eap_write_u24_t_network_order(
+				length_data,
+				3ul*sizeof(u8_t),
+				p_length));
+	}
+
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+}
+
+//-----------------------------------------------------------------------------
+
+/**
+ * This function resets the AVP header.
+ */
+eap_status_e eap_diameter_avp_header_c::reset_header(const u16_t data_length)
+{
+	eap_status_e status = set_avp_code(eap_diameter_avp_code_none);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	
+	status = set_avp_flag_vendor_specific(false);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	
+	status = set_avp_flag_mandatory_avp(false);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	
+	status = set_avp_flags_reserved();
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = set_data_length(data_length);
+	if (status != eap_status_ok)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-----------------------------------------------------------------------------
+// End.