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

This commit is contained in:
Łukasz Duda
2017-02-24 21:13:59 +01:00
committed by Jonathan Hui
parent fc45943f8c
commit 4f35cdb854
18 changed files with 323 additions and 214 deletions
+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)