[ICMPv6] Allow application to register ICMPv6 handler. (#1380)

This commit is contained in:
Łukasz Duda
2017-02-24 12:13:59 -08:00
committed by Jonathan Hui
parent fc45943f8c
commit 4f35cdb854
18 changed files with 323 additions and 214 deletions
@@ -786,7 +786,7 @@ otLwfEventWorkerThread(
NT_ASSERT(otCtxToFilter(pFilter->otCtx) == pFilter);
// Disable Icmp (ping) handling
otSetIcmpEchoEnabled(pFilter->otCtx, FALSE);
otIcmp6SetEchoEnabled(pFilter->otCtx, FALSE);
// Register callbacks with OpenThread
otSetStateChangedCallback(pFilter->otCtx, otLwfStateChangedCallback, pFilter);
+1
View File
@@ -62,6 +62,7 @@ RtlCopyBufferToMdl(
#include <openthread-windows-config.h>
#include <openthread-core-config.h>
#include <openthread.h>
#include <openthread-icmp6.h>
#include <openthread-ip6.h>
#include <openthread-tasklet.h>
#include <commissioning/commissioner.h>
+1 -1
View File
@@ -85,7 +85,7 @@ otPlatReset(
NT_ASSERT(otCtxToFilter(pFilter->otCtx) == pFilter);
// Disable Icmp (ping) handling
otSetIcmpEchoEnabled(pFilter->otCtx, FALSE);
otIcmp6SetEchoEnabled(pFilter->otCtx, FALSE);
// Register callbacks with OpenThread
otSetStateChangedCallback(pFilter->otCtx, otLwfStateChangedCallback, pFilter);
+1
View File
@@ -64,6 +64,7 @@ include_HEADERS = \
openthread-coap.h \
openthread-crypto.h \
openthread-diag.h \
openthread-icmp6.h \
openthread-ip6.h \
openthread-jam-detection.h \
openthread-message.h \
+111
View File
@@ -0,0 +1,111 @@
/*
* 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
* @brief
* This file defines the top-level icmp6 functions for the OpenThread library.
*/
#ifndef OPENTHREAD_ICMP6_H_
#define OPENTHREAD_ICMP6_H_
#include <openthread-types.h>
#include <openthread-message.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup icmp6 ICMPv6
*
* @brief
* This module includes functions that control ICMPv6 communication.
*
* @{
*
*/
/**
* This function indicates whether or not ICMPv6 Echo processing is enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval TRUE ICMPv6 Echo processing is enabled.
* @retval FALSE ICMPv6 Echo processing is disabled.
*
*/
bool otIcmp6IsEchoEnabled(otInstance *aInstance);
/**
* This function sets whether or not ICMPv6 Echo processing is enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnabled TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
*
*/
void otIcmp6SetEchoEnabled(otInstance *aInstance, bool aEnabled);
/**
* This function registers a handler to provide received ICMPv6 messages.
*
* @note A handler structure @p aHandler has to be stored in persistant (static) memory.
* OpenThread does not make a copy of handler structure.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aHandler A pointer to a handler conitaining callback that is called when
* an ICMPv6 message is received.
*
*/
ThreadError otIcmp6RegisterHandler(otInstance *aInstance, otIcmp6Handler *aHandler);
/**
* This function sends an ICMPv6 Echo Request via the Thread interface.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMessage A pointer to the message buffer containing the ICMPv6 payload.
* @param[in] aMessageInfo A reference to message information associated with @p aMessage.
* @param[in] aIdentifier An identifier to aid in matching Echo Replies to this Echo Request.
* May be zero.
*
*/
ThreadError otIcmp6SendEchoRequest(otInstance *aInstance, otMessage aMessage,
const otMessageInfo *aMessageInfo, uint16_t aIdentifier);
/**
* @}
*
*/
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_ICMP6_H_
-20
View File
@@ -342,26 +342,6 @@ void otSetReceiveIp6DatagramFilterEnabled(otInstance *aInstance, bool aEnabled);
*/
ThreadError otSendIp6Datagram(otInstance *aInstance, otMessage aMessage);
/**
* This function indicates whether or not ICMPv6 Echo processing is enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval TRUE ICMPv6 Echo processing is enabled.
* @retval FALSE ICMPv6 Echo processing is disabled.
*
*/
bool otIsIcmpEchoEnabled(otInstance *aInstance);
/**
* This function sets whether or not ICMPv6 Echo processing is enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnabled TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
*
*/
void otSetIcmpEchoEnabled(otInstance *aInstance, bool aEnabled);
/**
* @}
*
+95 -14
View File
@@ -329,6 +329,21 @@ struct otIp6Address
typedef struct otIp6Address otIp6Address;
/**
* This structure represents the local and peer IPv6 socket addresses.
*/
typedef struct otMessageInfo
{
otIp6Address mSockAddr; ///< The local IPv6 address.
otIp6Address mPeerAddr; ///< The peer IPv6 address.
uint16_t mSockPort; ///< The local transport-layer port.
uint16_t mPeerPort; ///< The peer transport-layer port.
int8_t mInterfaceId; ///< An IPv6 interface identifier.
uint8_t mHopLimit; ///< The IPv6 Hop Limit.
const void *mLinkInfo; ///< A pointer to link-specific information.
} otMessageInfo;
/**
* @addtogroup commands Commands
*
@@ -982,6 +997,86 @@ typedef struct
void *mData; ///< Opaque data used by the implementation.
} otMessageQueue;
/**
* @}
*
*/
/**
* @addtogroup icmp6 ICMPv6
*
* @brief
* This module includes functions that control ICMPv6 communication.
*
* @{
*
*/
/**
* ICMPv6 Message Types
*
*/
typedef enum otIcmp6Type
{
kIcmp6TypeDstUnreach = 1, ///< Destination Unreachable
kIcmp6TypeEchoRequest = 128, ///< Echo Request
kIcmp6TypeEchoReply = 129, ///< Echo Reply
} otIcmp6Type;
/**
* ICMPv6 Message Codes
*
*/
typedef enum otIcmp6Code
{
kIcmp6CodeDstUnreachNoRoute = 0, ///< Destination Unreachable No Route
} otIcmp6Code;
#define OT_ICMP6_HEADER_DATA_SIZE 4 ///< Size of an message specific data of ICMPv6 Header.
/**
* This structure represents an ICMPv6 header.
*
*/
OT_TOOL_PACKED_BEGIN
struct otIcmp6Header
{
uint8_t mType; ///< Type
uint8_t mCode; ///< Code
uint16_t mChecksum; ///< Checksum
union
{
uint8_t m8[OT_ICMP6_HEADER_DATA_SIZE / sizeof(uint8_t)];
uint16_t m16[OT_ICMP6_HEADER_DATA_SIZE / sizeof(uint16_t)];
uint32_t m32[OT_ICMP6_HEADER_DATA_SIZE / sizeof(uint32_t)];
} mData; ///< Message-specific data
} OT_TOOL_PACKED_END;
typedef struct otIcmp6Header otIcmp6Header;
/**
* This callback allows OpenThread to inform the application of a received ICMPv6 message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A pointer to the received message.
* @param[in] aMessageInfo A pointer to message information associated with @p aMessage.
* @param[in] aIcmpHeader A pointer to the received ICMPv6 header.
*
*/
typedef void (*otIcmp6ReceiveCallback)(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo,
const otIcmp6Header *aIcmpHeader);
/**
* This structure implements ICMPv6 message handler.
*
*/
typedef struct otIcmp6Handler
{
otIcmp6ReceiveCallback mReceiveCallback;
void *mContext;
struct otIcmp6Handler *mNext;
} otIcmp6Handler;
/**
* @}
*
@@ -1007,20 +1102,6 @@ typedef struct otSockAddr
int8_t mScopeId; ///< An IPv6 scope identifier.
} otSockAddr;
/**
* This structure represents the local and peer IPv6 socket addresses.
*/
typedef struct otMessageInfo
{
otIp6Address mSockAddr; ///< The local IPv6 address.
otIp6Address mPeerAddr; ///< The peer IPv6 address.
uint16_t mSockPort; ///< The local transport-layer port.
uint16_t mPeerPort; ///< The peer transport-layer port.
int8_t mInterfaceId; ///< An IPv6 interface identifier.
uint8_t mHopLimit; ///< The IPv6 Hop Limit.
const void *mLinkInfo; ///< A pointer to link-specific information.
} otMessageInfo;
/**
* This callback allows OpenThread to inform the application of a received UDP message.
*/
+26 -14
View File
@@ -44,6 +44,7 @@
#include <openthread.h>
#include <openthread-instance.h>
#include <openthread-diag.h>
#include <openthread-icmp6.h>
#include <commissioning/commissioner.h>
#include <commissioning/joiner.h>
#include <dhcp6/dhcp6_server.h>
@@ -144,10 +145,13 @@ Interpreter::Interpreter(otInstance *aInstance):
mInstance(aInstance)
{
memset(mSlaacAddresses, 0, sizeof(mSlaacAddresses));
mInstance->mIp6.mIcmp.SetEchoReplyHandler(&s_HandleEchoResponse, this);
otSetStateChangedCallback(mInstance, &Interpreter::s_HandleNetifStateChanged, this);
otSetReceiveDiagnosticGetCallback(mInstance, &Interpreter::s_HandleDiagnosticGetResponse, this);
mIcmpHandler.mReceiveCallback = Interpreter::s_HandleIcmpReceive;
mIcmpHandler.mContext = this;
otIcmp6RegisterHandler(mInstance, &mIcmpHandler);
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
memset(mDhcpAddresses, 0, sizeof(mDhcpAddresses));
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
@@ -1270,17 +1274,20 @@ exit:
AppendResult(error);
}
void Interpreter::s_HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void Interpreter::s_HandleIcmpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo,
const otIcmp6Header *aIcmpHeader)
{
static_cast<Interpreter *>(aContext)->HandleEchoResponse(aMessage, aMessageInfo);
static_cast<Interpreter *>(aContext)->HandleIcmpReceive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
*static_cast<const Ip6::IcmpHeader *>(aIcmpHeader));
}
void Interpreter::HandleEchoResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void Interpreter::HandleIcmpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
const Ip6::IcmpHeader &aIcmpHeader)
{
Ip6::IcmpHeader icmp6Header;
uint32_t timestamp = 0;
aMessage.Read(aMessage.GetOffset(), sizeof(icmp6Header), &icmp6Header);
VerifyOrExit(aIcmpHeader.GetType() == kIcmp6TypeEchoReply, ;);
sServer->OutputFormat("%d bytes from ", aMessage.GetLength() - aMessage.GetOffset());
sServer->OutputFormat("%x:%x:%x:%x:%x:%x:%x:%x",
@@ -1292,15 +1299,18 @@ void Interpreter::HandleEchoResponse(Message &aMessage, const Ip6::MessageInfo &
HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[5]),
HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[6]),
HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7]));
sServer->OutputFormat(": icmp_seq=%d hlim=%d", icmp6Header.GetSequence(), aMessageInfo.mHopLimit);
sServer->OutputFormat(": icmp_seq=%d hlim=%d", aIcmpHeader.GetSequence(), aMessageInfo.mHopLimit);
if (aMessage.Read(aMessage.GetOffset() + sizeof(icmp6Header), sizeof(uint32_t), &timestamp) >=
if (aMessage.Read(aMessage.GetOffset(), sizeof(uint32_t), &timestamp) >=
static_cast<int>(sizeof(uint32_t)))
{
sServer->OutputFormat(" time=%dms", Timer::GetNow() - HostSwap32(timestamp));
}
sServer->OutputFormat("\r\n");
exit:
return;
}
void Interpreter::ProcessPing(int argc, char *argv[])
@@ -1363,20 +1373,22 @@ void Interpreter::HandlePingTimer()
{
ThreadError error = kThreadError_None;
uint32_t timestamp = HostSwap32(Timer::GetNow());
Message *message;
VerifyOrExit((message = mInstance->mIp6.mIcmp.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = message->Append(&timestamp, sizeof(timestamp)));
SuccessOrExit(error = message->SetLength(sLength));
otMessage message;
const otMessageInfo *messageInfo = static_cast<const otMessageInfo *>(&sMessageInfo);
VerifyOrExit((message = otNewIp6Message(mInstance, true)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = otAppendMessage(message, &timestamp, sizeof(timestamp)));
SuccessOrExit(error = otSetMessageLength(message, sLength));
SuccessOrExit(error = otIcmp6SendEchoRequest(mInstance, message, messageInfo, 1));
SuccessOrExit(error = mInstance->mIp6.mIcmp.SendEchoRequest(*message, sMessageInfo));
sCount--;
exit:
if (error != kThreadError_None && message != NULL)
{
message->Free();
otFreeMessage(message);
}
if (sCount)
+6 -2
View File
@@ -218,7 +218,8 @@ private:
void ProcessVersion(int argc, char *argv[]);
void ProcessWhitelist(int argc, char *argv[]);
static void s_HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void s_HandleIcmpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo,
const otIcmp6Header *aIcmpHeader);
static void s_HandlePingTimer(void *aContext);
static void s_HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
static void s_HandleNetifStateChanged(uint32_t aFlags, void *aContext);
@@ -229,7 +230,8 @@ private:
static void s_HandleDiagnosticGetResponse(otMessage aMessage, const otMessageInfo *aMessageInfo, void *aContext);
static void s_HandleJoinerCallback(ThreadError aError, void *aContext);
void HandleEchoResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleIcmpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
const Ip6::IcmpHeader &aIcmpHeader);
void HandlePingTimer();
void HandleActiveScanResult(otActiveScanResult *aResult);
void HandleNetifStateChanged(uint32_t aFlags);
@@ -242,6 +244,7 @@ private:
static const struct Command sCommands[];
Ip6::MessageInfo sMessageInfo;
Server *sServer;
uint16_t sLength;
uint16_t sCount;
@@ -253,6 +256,7 @@ private:
otDhcpAddress mDhcpAddresses[OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES];
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
otIcmp6Handler mIcmpHandler;
otInstance *mInstance;
};
+15 -47
View File
@@ -50,8 +50,6 @@ namespace Ip6 {
Icmp::Icmp(Ip6 &aIp6):
mHandlers(NULL),
mEchoSequence(1),
mEchoReplyHandler(NULL),
mEchoReplyContext(NULL),
mIsEchoEnabled(true),
mIp6(aIp6)
{
@@ -62,11 +60,11 @@ Message *Icmp::NewMessage(uint16_t aReserved)
return mIp6.NewMessage(sizeof(IcmpHeader) + aReserved);
}
ThreadError Icmp::RegisterCallbacks(IcmpHandler &aHandler)
ThreadError Icmp::RegisterHandler(IcmpHandler &aHandler)
{
ThreadError error = kThreadError_None;
for (IcmpHandler *cur = mHandlers; cur; cur = cur->mNext)
for (IcmpHandler *cur = mHandlers; cur; cur = cur->GetNext())
{
if (cur == &aHandler)
{
@@ -81,13 +79,8 @@ exit:
return error;
}
void Icmp::SetEchoReplyHandler(EchoReplyHandler aHandler, void *aContext)
{
mEchoReplyHandler = aHandler;
mEchoReplyContext = aContext;
}
ThreadError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo)
ThreadError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo,
uint16_t aIdentifier)
{
ThreadError error = kThreadError_None;
MessageInfo messageInfoLocal;
@@ -96,8 +89,8 @@ ThreadError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessage
messageInfoLocal = aMessageInfo;
icmpHeader.Init();
icmpHeader.SetType(IcmpHeader::kTypeEchoRequest);
icmpHeader.SetId(1);
icmpHeader.SetType(kIcmp6TypeEchoRequest);
icmpHeader.SetId(aIdentifier);
icmpHeader.SetSequence(mEchoSequence++);
SuccessOrExit(error = aMessage.Prepend(&icmpHeader, sizeof(icmpHeader)));
@@ -160,35 +153,22 @@ ThreadError Icmp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
checksum = aMessage.UpdateChecksum(checksum, aMessage.GetOffset(), payloadLength);
VerifyOrExit(checksum == 0xffff, ;);
switch (icmp6Header.GetType())
if (mIsEchoEnabled && (icmp6Header.GetType() == kIcmp6TypeEchoRequest))
{
case IcmpHeader::kTypeEchoRequest:
return HandleEchoRequest(aMessage, aMessageInfo);
HandleEchoRequest(aMessage, aMessageInfo);
}
case IcmpHeader::kTypeEchoReply:
return HandleEchoReply(aMessage, aMessageInfo);
aMessage.MoveOffset(sizeof(icmp6Header));
case IcmpHeader::kTypeDstUnreach:
return HandleDstUnreach(aMessage, aMessageInfo, icmp6Header);
for (IcmpHandler *handler = mHandlers; handler; handler = handler->GetNext())
{
handler->HandleReceiveMessage(aMessage, aMessageInfo, icmp6Header);
}
exit:
return error;
}
ThreadError Icmp::HandleDstUnreach(Message &aMessage, const MessageInfo &aMessageInfo,
const IcmpHeader &aIcmpheader)
{
aMessage.MoveOffset(sizeof(aIcmpheader));
for (IcmpHandler *handler = mHandlers; handler; handler = handler->mNext)
{
handler->HandleDstUnreach(aMessage, aMessageInfo, aIcmpheader);
}
return kThreadError_None;
}
ThreadError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo)
{
ThreadError error = kThreadError_None;
@@ -197,16 +177,14 @@ ThreadError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo
MessageInfo replyMessageInfo;
uint16_t payloadLength;
VerifyOrExit(mIsEchoEnabled, ;);
otLogInfoIcmp("Received Echo Request");
icmp6Header.Init();
icmp6Header.SetType(IcmpHeader::kTypeEchoReply);
icmp6Header.SetType(kIcmp6TypeEchoReply);
if ((replyMessage = mIp6.NewMessage(0)) == NULL)
{
otLogDebgIcmp("icmp fail");
otLogDebgIcmp("Failed to allocate a new message");
ExitNow();
}
@@ -241,16 +219,6 @@ exit:
return error;
}
ThreadError Icmp::HandleEchoReply(Message &aMessage, const MessageInfo &aMessageInfo)
{
VerifyOrExit(mIsEchoEnabled && mEchoReplyHandler, ;);
mEchoReplyHandler(mEchoReplyContext, aMessage, aMessageInfo);
exit:
return kThreadError_None;
}
ThreadError Icmp::UpdateChecksum(Message &aMessage, uint16_t aChecksum)
{
aChecksum = aMessage.UpdateChecksum(aChecksum, aMessage.GetOffset(),
+28 -94
View File
@@ -34,6 +34,7 @@
#ifndef ICMP6_HPP_
#define ICMP6_HPP_
#include <openthread-types.h>
#include <common/encoding.hpp>
#include <net/ip6_headers.hpp>
@@ -52,35 +53,12 @@ namespace Ip6 {
*
*/
enum
{
kIcmp6DataSize = 4,
};
/**
* This structure represents an ICMPv6 header.
*
*/
OT_TOOL_PACKED_BEGIN
struct IcmpHeaderPoD
{
uint8_t mType; ///< Type
uint8_t mCode; ///< Code
uint16_t mChecksum; ///< Checksum
union
{
uint8_t m8[kIcmp6DataSize / sizeof(uint8_t)];
uint16_t m16[kIcmp6DataSize / sizeof(uint16_t)];
uint32_t m32[kIcmp6DataSize / sizeof(uint32_t)];
} mData; ///< Message-specific data
} OT_TOOL_PACKED_END;
/**
/*
* This class implements ICMPv6 header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class IcmpHeader: private IcmpHeaderPoD
class IcmpHeader: public otIcmp6Header
{
public:
/**
@@ -93,12 +71,13 @@ public:
* ICMPv6 Message Types
*
*/
enum Type
{
kTypeDstUnreach = 1, ///< Destination Unreachable
kTypeEchoRequest = 128, ///< Echo Request
kTypeEchoReply = 129, ///< Echo Reply
};
typedef otIcmp6Type Type;
/**
* ICMPv6 Message Codes
*
*/
typedef otIcmp6Code Code;
/**
* This method returns the ICMPv6 message type.
@@ -116,15 +95,6 @@ public:
*/
void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
/**
* ICMPv6 Message Codes
*
*/
enum Code
{
kCodeDstUnreachNoRoute = 0, ///< Destination Unreachable No Route
};
/**
* This method returns the ICMPv6 message code.
*
@@ -194,7 +164,7 @@ public:
* @returns The byte offset of the Checksum field.
*
*/
static uint8_t GetChecksumOffset(void) { return offsetof(IcmpHeaderPoD, mChecksum); }
static uint8_t GetChecksumOffset(void) { return offsetof(otIcmp6Header, mChecksum); }
/**
* This static method returns the byte offset of the ICMPv6 payload.
@@ -202,7 +172,7 @@ public:
* @returns The Byte offset of the ICMPv6 payload.
*
*/
static uint8_t GetDataOffset(void) { return offsetof(IcmpHeaderPoD, mData); }
static uint8_t GetDataOffset(void) { return offsetof(otIcmp6Header, mData); }
} OT_TOOL_PACKED_END;
@@ -210,45 +180,30 @@ public:
* This class implements ICMPv6 message handlers.
*
*/
class IcmpHandler
class IcmpHandler : public otIcmp6Handler
{
friend class Icmp;
public:
/**
* This function pointer is called when receiving an ICMPv6 Destination Unreachable message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the received message.
* @param[in] aMessageInfo A reference to message information associated with @p aMessage.
* @param[in] aIcmpHeader A reference to the received ICMPv6 header.
*
*/
typedef void (*DstUnreachHandler)(void *aContext, Message &aMesage, const MessageInfo &aMessageInfo,
const IcmpHeader &aIcmpHeader);
/**
* This constructor creates an ICMPv6 message handler.
*
* @param[in] aDstUnreachHandler A pointer to the function that is called when receiving a Destination
* Unreachable message.
* @param[in] aContext A pointer to arbitrary context information.
* @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.
*
*/
IcmpHandler(DstUnreachHandler aDstUnreachHandler, void *aContext) {
mDstUnreachHandler = aDstUnreachHandler;
mContext = aContext;
mNext = NULL;
IcmpHandler(otIcmp6ReceiveCallback aCallback, void *aContext) {
mReceiveCallback = aCallback;
mContext = aContext;
mNext = NULL;
}
private:
void HandleDstUnreach(Message &message, const MessageInfo &messageInfo, const IcmpHeader &icmp6Header) {
mDstUnreachHandler(mContext, message, messageInfo, icmp6Header);
void HandleReceiveMessage(Message &message, const MessageInfo &messageInfo, const IcmpHeader &icmp6Header) {
mReceiveCallback(mContext, &message, &messageInfo, &icmp6Header);
}
DstUnreachHandler mDstUnreachHandler;
void *mContext;
IcmpHandler *mNext;
IcmpHandler *GetNext(void) { return static_cast<IcmpHandler *>(mNext); }
};
/**
@@ -277,46 +232,29 @@ public:
Message *NewMessage(uint16_t aReserved);
/**
* This method registers ICMPv6 handlers.
* This method registers ICMPv6 handler.
*
* @param[in] aHandler A reference to the ICMPv6 handler.
*
* @retval kThreadError_None Successfully registered the ICMPv6 handler.
* @retval kThreadError_None Successfully registered the ICMPv6 handler.
* @retval kThreadError_Already The ICMPv6 handler is already registered.
*
*/
ThreadError RegisterCallbacks(IcmpHandler &aHandler);
/**
* This function pointer is called when receiving an ICMPv6 Echo Reply in response to an Echo Request.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the received message.
* @param[in] aMessageInfo A reference to message information associated with @p aMessage.
*
*/
typedef void (*EchoReplyHandler)(void *aContext, Message &aMessage, const MessageInfo &aMessageInfo);
/**
* This method sets the Echo Reply handler.
*
* @param[in] aHandler A pointer to a function that is called when receiving an ICMPv6 Echo Reply.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
void SetEchoReplyHandler(EchoReplyHandler aHandler, void *aContext);
ThreadError RegisterHandler(IcmpHandler &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 kThreadError_None Successfully enqueued the ICMPv6 Echo Request message.
* @retval kThreadError_NoBufs Insufficient buffers available to generate an ICMPv6 Echo Request message.
*
*/
ThreadError SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo);
ThreadError SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier);
/**
* This method sends an ICMPv6 error message.
@@ -376,15 +314,11 @@ public:
void SetEchoEnabled(bool aEnabled);
private:
ThreadError HandleDstUnreach(Message &aMessage, const MessageInfo &aMessageInfo, const IcmpHeader &aIcmpHeader);
ThreadError HandleEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo);
ThreadError HandleEchoReply(Message &aMessage, const MessageInfo &aMessageInfo);
IcmpHandler *mHandlers;
uint16_t mEchoSequence;
EchoReplyHandler mEchoReplyHandler;
void *mEchoReplyContext;
bool mIsEchoEnabled;
Ip6 &mIp6;
+1 -1
View File
@@ -617,7 +617,7 @@ ThreadError Ip6::ProcessReceiveCallback(const Message &aMessage, const MessageIn
aMessage.Read(aMessage.GetOffset(), sizeof(icmp), &icmp);
// do not pass ICMP Echo Request messages
VerifyOrExit(icmp.GetType() != IcmpHeader::kTypeEchoRequest, error = kThreadError_NoRoute);
VerifyOrExit(icmp.GetType() != kIcmp6TypeEchoRequest, error = kThreadError_NoRoute);
}
break;
+15 -2
View File
@@ -1752,16 +1752,29 @@ ThreadError otSendUdp(otUdpSocket *aSocket, otMessage aMessage, const otMessageI
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
bool otIsIcmpEchoEnabled(otInstance *aInstance)
bool otIcmp6IsEchoEnabled(otInstance *aInstance)
{
return aInstance->mIp6.mIcmp.IsEchoEnabled();
}
void otSetIcmpEchoEnabled(otInstance *aInstance, bool aEnabled)
void otIcmp6SetEchoEnabled(otInstance *aInstance, bool aEnabled)
{
aInstance->mIp6.mIcmp.SetEchoEnabled(aEnabled);
}
ThreadError otIcmp6RegisterHandler(otInstance *aInstance, otIcmp6Handler *aHandler)
{
return aInstance->mIp6.mIcmp.RegisterHandler(*static_cast<Ip6::IcmpHandler *>(aHandler));
}
ThreadError otIcmp6SendEchoRequest(otInstance *aInstance, otMessage aMessage,
const otMessageInfo *aMessageInfo, uint16_t aIdentifier)
{
return aInstance->mIp6.mIcmp.SendEchoRequest(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
aIdentifier);
}
uint8_t otIp6PrefixMatch(const otIp6Address *aFirst, const otIp6Address *aSecond)
{
uint8_t rval;
+11 -8
View File
@@ -55,7 +55,7 @@ AddressResolver::AddressResolver(ThreadNetif &aThreadNetif) :
mAddressError(OPENTHREAD_URI_ADDRESS_ERROR, &AddressResolver::HandleAddressError, this),
mAddressQuery(OPENTHREAD_URI_ADDRESS_QUERY, &AddressResolver::HandleAddressQuery, this),
mAddressNotification(OPENTHREAD_URI_ADDRESS_NOTIFY, &AddressResolver::HandleAddressNotification, this),
mIcmpHandler(&AddressResolver::HandleDstUnreach, this),
mIcmpHandler(&AddressResolver::HandleIcmpReceive, this),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, &AddressResolver::HandleTimer, this),
mNetif(aThreadNetif)
{
@@ -65,7 +65,7 @@ AddressResolver::AddressResolver(ThreadNetif &aThreadNetif) :
mNetif.GetCoapServer().AddResource(mAddressQuery);
mNetif.GetCoapServer().AddResource(mAddressNotification);
mNetif.GetIp6().mIcmp.RegisterCallbacks(mIcmpHandler);
mNetif.GetIp6().mIcmp.RegisterHandler(mIcmpHandler);
}
void AddressResolver::Clear()
@@ -645,20 +645,23 @@ void AddressResolver::HandleTimer()
}
}
void AddressResolver::HandleDstUnreach(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
const Ip6::IcmpHeader &aIcmpHeader)
void AddressResolver::HandleIcmpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo,
const otIcmp6Header *aIcmpHeader)
{
static_cast<AddressResolver *>(aContext)->HandleDstUnreach(aMessage, aMessageInfo, aIcmpHeader);
static_cast<AddressResolver *>(aContext)->HandleIcmpReceive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
*static_cast<const Ip6::IcmpHeader *>(aIcmpHeader));
(void)aMessageInfo;
}
void AddressResolver::HandleDstUnreach(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
const Ip6::IcmpHeader &aIcmpHeader)
void AddressResolver::HandleIcmpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
const Ip6::IcmpHeader &aIcmpHeader)
{
Ip6::Header ip6Header;
VerifyOrExit(aIcmpHeader.GetCode() == Ip6::IcmpHeader::kCodeDstUnreachNoRoute, ;);
VerifyOrExit(aIcmpHeader.GetType() == kIcmp6TypeDstUnreach, ;);
VerifyOrExit(aIcmpHeader.GetCode() == kIcmp6CodeDstUnreachNoRoute, ;);
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(ip6Header), &ip6Header) == sizeof(ip6Header), ;);
for (int i = 0; i < kCacheEntries; i++)
+3 -3
View File
@@ -174,9 +174,9 @@ private:
const otMessageInfo *aMessageInfo);
void HandleAddressNotification(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDstUnreach(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
const Ip6::IcmpHeader &aIcmpHeader);
void HandleDstUnreach(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Ip6::IcmpHeader &aIcmpHeader);
static void HandleIcmpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo,
const otIcmp6Header *aIcmpHeader);
void HandleIcmpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Ip6::IcmpHeader &aIcmpHeader);
static void HandleTimer(void *aContext);
void HandleTimer(void);
+2 -2
View File
@@ -3203,8 +3203,8 @@ ThreadError Mle::CheckReachability(uint16_t aMeshSource, uint16_t aMeshDest, Ip6
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(aMeshSource);
messageInfo.SetInterfaceId(mNetif.GetInterfaceId());
mNetif.GetIp6().mIcmp.SendError(Ip6::IcmpHeader::kTypeDstUnreach,
Ip6::IcmpHeader::kCodeDstUnreachNoRoute,
mNetif.GetIp6().mIcmp.SendError(kIcmp6TypeDstUnreach,
kIcmp6CodeDstUnreachNoRoute,
messageInfo, aIp6Header);
exit:
+2 -2
View File
@@ -3632,8 +3632,8 @@ ThreadError MleRouter::CheckReachability(uint16_t aMeshSource, uint16_t aMeshDes
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(aMeshSource);
messageInfo.SetInterfaceId(mNetif.GetInterfaceId());
mNetif.GetIp6().mIcmp.SendError(Ip6::IcmpHeader::kTypeDstUnreach,
Ip6::IcmpHeader::kCodeDstUnreachNoRoute,
mNetif.GetIp6().mIcmp.SendError(kIcmp6TypeDstUnreach,
kIcmp6CodeDstUnreachNoRoute,
messageInfo, aIp6Header);
return kThreadError_Drop;
+4 -3
View File
@@ -44,6 +44,7 @@
#include <net/ip6.hpp>
#include <openthread.h>
#include <openthread-diag.h>
#include <openthread-icmp6.h>
#if OPENTHREAD_ENABLE_JAM_DETECTION
#include <openthread-jam-detection.h>
#endif
@@ -515,7 +516,7 @@ NcpBase::NcpBase(otInstance *aInstance):
otSetStateChangedCallback(mInstance, &NcpBase::HandleNetifStateChanged, this);
otSetReceiveIp6DatagramCallback(mInstance, &NcpBase::HandleDatagramFromStack, this);
otSetLinkPcapCallback(mInstance, &NcpBase::HandleRawFrame, static_cast<void*>(this));
otSetIcmpEchoEnabled(mInstance, false);
otIcmp6SetEchoEnabled(mInstance, false);
otSetReceiveIp6DatagramFilterEnabled(mInstance, true);
mUpdateChangedPropsTask.Post();
@@ -2711,7 +2712,7 @@ ThreadError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(uint8_t header, s
SPINEL_CMD_PROP_VALUE_IS,
key,
SPINEL_DATATYPE_BOOL_S,
otIsIcmpEchoEnabled(mInstance)
otIcmp6IsEchoEnabled(mInstance)
);
}
@@ -4379,7 +4380,7 @@ ThreadError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(uint8_t header, s
if (parsedLength > 0)
{
otSetIcmpEchoEnabled(mInstance, isEnabled);
otIcmp6SetEchoEnabled(mInstance, isEnabled);
errorCode = HandleCommandPropertyGet(header, key);
}