blob: ba73d6093f376956328a60f9de787dc7077acd5d [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for ICMPv6.
*/
#ifndef ICMP6_HPP_
#define ICMP6_HPP_
#include "openthread-core-config.h"
#include <openthread/icmp6.h>
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "net/ip6_headers.hpp"
namespace ot {
namespace Ip6 {
using ot::Encoding::BigEndian::HostSwap16;
/**
* @addtogroup core-ip6-icmp6
*
* @brief
* This module includes definitions for ICMPv6.
*
* @{
*
*/
/**
* This class implements ICMPv6.
*
*/
class Icmp : public InstanceLocator, private NonCopyable
{
public:
/*
* This class implements ICMPv6 header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class Header : public otIcmp6Header, public Clearable<Header>
{
public:
/**
* ICMPv6 Message Types
*
*/
enum Type : uint8_t
{
kTypeDstUnreach = OT_ICMP6_TYPE_DST_UNREACH, ///< Destination Unreachable
kTypePacketToBig = OT_ICMP6_TYPE_PACKET_TO_BIG, ///< Packet To Big
kTypeTimeExceeded = OT_ICMP6_TYPE_TIME_EXCEEDED, ///< Time Exceeded
kTypeParameterProblem = OT_ICMP6_TYPE_PARAMETER_PROBLEM, ///< Parameter Problem
kTypeEchoRequest = OT_ICMP6_TYPE_ECHO_REQUEST, ///< Echo Request
kTypeEchoReply = OT_ICMP6_TYPE_ECHO_REPLY, ///< Echo Reply
kTypeRouterSolicit = OT_ICMP6_TYPE_ROUTER_SOLICIT, ///< Router Solicitation
kTypeRouterAdvert = OT_ICMP6_TYPE_ROUTER_ADVERT, ///< Router Advertisement
};
/**
* ICMPv6 Message Codes
*
*/
enum Code : uint8_t
{
kCodeDstUnreachNoRoute = OT_ICMP6_CODE_DST_UNREACH_NO_ROUTE, ///< Destination Unreachable No Route
kCodeFragmReasTimeEx = OT_ICMP6_CODE_FRAGM_REAS_TIME_EX, ///< Fragment Reassembly Time Exceeded
};
static constexpr uint8_t kTypeFieldOffset = 0; ///< The byte offset of Type field in ICMP6 header.
static constexpr uint8_t kCodeFieldOffset = 1; ///< The byte offset of Code field in ICMP6 header.
static constexpr uint8_t kChecksumFieldOffset = 2; ///< The byte offset of Checksum field in ICMP6 header.
static constexpr uint8_t kDataFieldOffset = 4; ///< The byte offset of Data field in ICMP6 header.
/**
* This method indicates whether the ICMPv6 message is an error message.
*
* @retval TRUE if the ICMPv6 message is an error message.
* @retval FALSE if the ICMPv6 message is an informational message.
*
*/
bool IsError(void) const { return mType < OT_ICMP6_TYPE_ECHO_REQUEST; }
/**
* This method returns the ICMPv6 message type.
*
* @returns The ICMPv6 message type.
*
*/
Type GetType(void) const { return static_cast<Type>(mType); }
/**
* This method sets the ICMPv6 message type.
*
* @param[in] aType The ICMPv6 message type.
*
*/
void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
/**
* This method returns the ICMPv6 message code.
*
* @returns The ICMPv6 message code.
*
*/
Code GetCode(void) const { return static_cast<Code>(mCode); }
/**
* This method sets the ICMPv6 message code.
*
* @param[in] aCode The ICMPv6 message code.
*
*/
void SetCode(Code aCode) { mCode = static_cast<uint8_t>(aCode); }
/**
* This method returns the ICMPv6 message checksum.
*
* @returns The ICMPv6 message checksum.
*
*/
uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
/**
* This method sets the ICMPv6 message checksum.
*
* @param[in] aChecksum The ICMPv6 message checksum.
*
*/
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
/**
* This method returns the ICMPv6 message ID for Echo Requests and Replies.
*
* @returns The ICMPv6 message ID.
*
*/
uint16_t GetId(void) const { return HostSwap16(mData.m16[0]); }
/**
* This method sets the ICMPv6 message ID for Echo Requests and Replies.
*
* @param[in] aId The ICMPv6 message ID.
*
*/
void SetId(uint16_t aId) { mData.m16[0] = HostSwap16(aId); }
/**
* This method returns the ICMPv6 message sequence for Echo Requests and Replies.
*
* @returns The ICMPv6 message sequence.
*
*/
uint16_t GetSequence(void) const { return HostSwap16(mData.m16[1]); }
/**
* This method sets the ICMPv6 message sequence for Echo Requests and Replies.
*
* @param[in] aSequence The ICMPv6 message sequence.
*
*/
void SetSequence(uint16_t aSequence) { mData.m16[1] = HostSwap16(aSequence); }
} OT_TOOL_PACKED_END;
/**
* This class implements ICMPv6 message handlers.
*
*/
class Handler : public otIcmp6Handler, public LinkedListEntry<Handler>
{
friend class Icmp;
public:
/**
* This constructor creates an ICMPv6 message handler.
*
* @param[in] aCallback A pointer to the function that is called when receiving an ICMPv6 message.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
Handler(otIcmp6ReceiveCallback aCallback, void *aContext)
{
mReceiveCallback = aCallback;
mContext = aContext;
mNext = nullptr;
}
private:
void HandleReceiveMessage(Message &aMessage, const MessageInfo &aMessageInfo, const Header &aIcmp6Header)
{
mReceiveCallback(mContext, &aMessage, &aMessageInfo, &aIcmp6Header);
}
};
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Icmp(Instance &aInstance);
/**
* This method returns a new ICMP message with sufficient header space reserved.
*
* @param[in] aReserved The number of header bytes to reserve after the ICMP header.
*
* @returns A pointer to the message or `nullptr` if no buffers are available.
*
*/
Message *NewMessage(uint16_t aReserved);
/**
* This method registers ICMPv6 handler.
*
* @param[in] aHandler A reference to the ICMPv6 handler.
*
* @retval kErrorNone Successfully registered the ICMPv6 handler.
* @retval kErrorAlready The ICMPv6 handler is already registered.
*
*/
Error RegisterHandler(Handler &aHandler);
/**
* This method sends an ICMPv6 Echo Request message.
*
* @param[in] aMessage A reference to the Echo Request payload.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aIdentifier An identifier to aid in matching Echo Replies to this Echo Request.
* May be zero.
*
* @retval kErrorNone Successfully enqueued the ICMPv6 Echo Request message.
* @retval kErrorNoBufs Insufficient buffers available to generate an ICMPv6 Echo Request message.
*
*/
Error SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier);
/**
* This method sends an ICMPv6 error message.
*
* @param[in] aType The ICMPv6 message type.
* @param[in] aCode The ICMPv6 message code.
* @param[in] aMessageInfo A reference to the message info.
* @param[in] aMessage The error-causing IPv6 message.
*
* @retval kErrorNone Successfully enqueued the ICMPv6 error message.
* @retval kErrorNoBufs Insufficient buffers available.
*
*/
Error SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage);
/**
* This method handles an ICMPv6 message.
*
* @param[in] aMessage A reference to the ICMPv6 message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
* @retval kErrorNone Successfully processed the ICMPv6 message.
* @retval kErrorNoBufs Insufficient buffers available to generate the reply.
* @retval kErrorDrop The ICMPv6 message was invalid and dropped.
*
*/
Error HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
/**
* This method indicates whether or not ICMPv6 Echo processing is enabled.
*
* @retval TRUE ICMPv6 Echo processing is enabled.
* @retval FALSE ICMPv6 Echo processing is disabled.
*
*/
otIcmp6EchoMode GetEchoMode(void) const { return mEchoMode; }
/**
* Sets the ICMPv6 echo mode.
*
* @param[in] aMode The ICMPv6 echo mode.
*
*/
void SetEchoMode(otIcmp6EchoMode aMode) { mEchoMode = aMode; }
/**
* This method indicates whether or not the ICMPv6 Echo Request should be handled.
*
* @retval TRUE if OpenThread should respond with an ICMPv6 Echo Reply.
* @retval FALSE if OpenThread should not respond with an ICMPv6 Echo Reply.
*
*/
bool ShouldHandleEchoRequest(const MessageInfo &aMessageInfo);
/**
* This method returns the ICMPv6 Echo sequence number.
*
* @returns The sequence number of the next ICMPv6 Echo request.
*
*/
uint16_t GetEchoSequence(void) const { return mEchoSequence; }
private:
Error HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
LinkedList<Handler> mHandlers;
uint16_t mEchoSequence;
otIcmp6EchoMode mEchoMode;
};
/**
* @}
*
*/
} // namespace Ip6
DefineCoreType(otIcmp6Header, Ip6::Icmp::Header);
DefineCoreType(otIcmp6Handler, Ip6::Icmp::Handler);
} // namespace ot
#endif // ICMP6_HPP_