#ifndef ICMP6_HPP_
#define ICMP6_HPP_
#include "openthread-core-config.h"
#include <openthread/icmp6.h>
#include "common/encoding.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "net/ip6_headers.hpp"
namespace ot {
namespace Ip6 {
using ot::Encoding::BigEndian::HostSwap16;
OT_TOOL_PACKED_BEGIN
class IcmpHeader : public otIcmp6Header
{
public:
void Init(void)
{
mType = 0;
mCode = 0;
mChecksum = 0;
mData.m32[0] = 0;
}
enum Type
{
kTypeDstUnreach = OT_ICMP6_TYPE_DST_UNREACH, kTypePacketToBig = OT_ICMP6_TYPE_PACKET_TO_BIG, kTypeTimeExceeded = OT_ICMP6_TYPE_TIME_EXCEEDED, kTypeParameterProblem = OT_ICMP6_TYPE_PARAMETER_PROBLEM, kTypeEchoRequest = OT_ICMP6_TYPE_ECHO_REQUEST, kTypeEchoReply = OT_ICMP6_TYPE_ECHO_REPLY, };
enum Code
{
kCodeDstUnreachNoRoute = OT_ICMP6_CODE_DST_UNREACH_NO_ROUTE, kCodeFragmReasTimeEx = OT_ICMP6_CODE_FRAGM_REAS_TIME_EX, };
bool IsError(void) const { return mType < OT_ICMP6_TYPE_ECHO_REQUEST; }
Type GetType(void) const { return static_cast<Type>(mType); }
void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
Code GetCode(void) const { return static_cast<Code>(mCode); }
void SetCode(Code aCode) { mCode = static_cast<uint8_t>(aCode); }
uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
uint16_t GetId(void) const { return HostSwap16(mData.m16[0]); }
void SetId(uint16_t aId) { mData.m16[0] = HostSwap16(aId); }
uint16_t GetSequence(void) const { return HostSwap16(mData.m16[1]); }
void SetSequence(uint16_t aSequence) { mData.m16[1] = HostSwap16(aSequence); }
static uint8_t GetChecksumOffset(void) { return offsetof(otIcmp6Header, mChecksum); }
static uint8_t GetDataOffset(void) { return offsetof(otIcmp6Header, mData); }
} OT_TOOL_PACKED_END;
class IcmpHandler : public otIcmp6Handler, public LinkedListEntry<IcmpHandler>
{
friend class Icmp;
public:
IcmpHandler(otIcmp6ReceiveCallback aCallback, void *aContext)
{
mReceiveCallback = aCallback;
mContext = aContext;
mNext = NULL;
}
private:
void HandleReceiveMessage(Message &aMessage, const MessageInfo &aMessageInfo, const IcmpHeader &aIcmp6Header)
{
mReceiveCallback(mContext, &aMessage, &aMessageInfo, &aIcmp6Header);
}
};
class Icmp : public InstanceLocator
{
public:
explicit Icmp(Instance &aInstance);
Message *NewMessage(uint16_t aReserved);
otError RegisterHandler(IcmpHandler &aHandler);
otError SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier);
otError SendError(IcmpHeader::Type aType,
IcmpHeader::Code aCode,
const MessageInfo &aMessageInfo,
const Message & aMessage);
otError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
void UpdateChecksum(Message &aMessage, uint16_t aChecksum);
otIcmp6EchoMode GetEchoMode(void) const { return mEchoMode; }
void SetEchoMode(otIcmp6EchoMode aMode) { mEchoMode = aMode; }
bool ShouldHandleEchoRequest(const MessageInfo &aMessageInfo);
private:
otError HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
LinkedList<IcmpHandler> mHandlers;
uint16_t mEchoSequence;
otIcmp6EchoMode mEchoMode;
};
} }
#endif