--- /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.