From 8195ed9c623f022de0d09b7b85c3521064b876f7 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Fri, 19 Aug 2016 14:35:09 -0700 Subject: [PATCH] Allow client to specify whether or not to filter Thread control traffic. (#423) --- include/openthread.h | 35 +++++++++++++++++++++++++++++++++-- src/core/net/ip6.cpp | 31 +++++++++++++++++++++++++++++++ src/core/net/ip6.hpp | 32 +++++++++++++++++++++++++++++++- src/core/openthread.cpp | 10 ++++++++++ 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/include/openthread.h b/include/openthread.h index 3442379e8..a5e2c0935 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -1635,13 +1635,44 @@ typedef void (*otReceiveIp6DatagramCallback)(otMessage aMessage, void *aContext) /** * This function registers a callback to provide received IPv6 datagrams. * - * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received or - * NULL to disable the callback. + * By default, this callback does not pass Thread control traffic. See otSetReceiveIp6FilterEnabled() to change + * the Thread control traffic filter setting. + * + * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received + * or NULL to disable the callback. * @param[in] aCallbackContext A pointer to application-specific context. * + * @sa otIsReceiveIp6FilterEnabled + * @sa otSetReceiveIp6FilterEnabled + * */ void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback, void *aCallbackContext); + +/** + * This function indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams + * via the callback specified in otSetReceiveIp6DatagramCallback(). + * + * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise. + * + * @sa otSetReceiveDatagramCallback + * @sa otSetReceiveIp6FilterEnabled + * + */ +bool otIsReceiveIp6DatagramFilterEnabled(void); + +/** + * This function sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams + * via the callback specified in otSetReceiveIp6DatagramCallback(). + * + * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise. + * + * @sa otSetReceiveDatagramCallback + * @sa otIsReceiveIp6FilterEnabled + * + */ +void otSetReceiveIp6DatagramFilterEnabled(bool aEnabled); + /** * This function sends an IPv6 datagram via the Thread interface. * diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 6b7b7f758..3b65c4720 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -43,6 +43,7 @@ #include #include #include +#include namespace Thread { namespace Ip6 { @@ -53,6 +54,7 @@ static bool sForwardingEnabled; static otReceiveIp6DatagramCallback sReceiveIp6DatagramCallback = NULL; static void *sReceiveIp6DatagramCallbackContext = NULL; +static bool sIsReceiveIp6FilterEnabled; static ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo); @@ -66,6 +68,7 @@ void Ip6::Init(void) { sMpl = new(&sMplBuf) Mpl; sForwardingEnabled = false; + sIsReceiveIp6FilterEnabled = true; } void Ip6::SetForwardingEnabled(bool aEnable) @@ -114,6 +117,16 @@ void Ip6::SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback, voi sReceiveIp6DatagramCallbackContext = aCallbackContext; } +bool Ip6::IsReceiveIp6FilterEnabled(void) +{ + return sIsReceiveIp6FilterEnabled; +} + +void Ip6::SetReceiveIp6FilterEnabled(bool aEnabled) +{ + sIsReceiveIp6FilterEnabled = aEnabled; +} + ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength) { ThreadError error = kThreadError_None; @@ -328,6 +341,24 @@ void Ip6::ProcessReceiveCallback(Message &aMessage) VerifyOrExit(sReceiveIp6DatagramCallback != NULL, ;); + if (sIsReceiveIp6FilterEnabled) + { + Header ip6; + aMessage.Read(0, sizeof(ip6), &ip6); + + // do not pass messages sent to/from an RLOC + VerifyOrExit(!ip6.GetSource().IsRoutingLocator() && !ip6.GetDestination().IsRoutingLocator(), ;); + + if (ip6.GetSource().IsLinkLocal() && ip6.GetNextHeader() == kProtoUdp) + { + UdpHeader udp; + aMessage.Read(sizeof(ip6), sizeof(udp), &udp); + + // do not pass MLE messages + VerifyOrExit(udp.GetDestinationPort() != Mle::kUdpPort, ;); + } + } + // make a copy of the datagram to pass to host VerifyOrExit((messageCopy = NewMessage(0)) != NULL, error = kThreadError_NoBufs); SuccessOrExit(error = messageCopy->SetLength(aMessage.GetLength())); diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index 4506a744e..834dc0fa1 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -575,15 +575,45 @@ public: uint16_t aLength, IpProto aProto); /** - * This function registers a callback to provide received raw IPv6 datagrams. + * This method registers a callback to provide received raw IPv6 datagrams. + * + * By default, this callback does not pass Thread control traffic. See SetReceiveIp6FilterEnabled() to change + * the Thread control traffic filter setting. * * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received * or NULL to disable the callback. * @param[in] aCallbackContext A pointer to application-specific context. * + * @sa IsReceiveIp6FilterEnabled + * @sa SetReceiveIp6FilterEnabled + * */ static void SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback, void *aCallbackContext); + /** + * This method indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams + * via the callback specified in SetReceiveIp6DatagramCallback(). + * + * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise. + * + * @sa SetReceiveDatagramCallback + * @sa SetReceiveIp6FilterEnabled + * + */ + static bool IsReceiveIp6FilterEnabled(void); + + /** + * This method sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams + * via the callback specified in SetReceiveIp6DatagramCallback(). + * + * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise. + * + * @sa SetReceiveDatagramCallback + * @sa IsReceiveIp6FilterEnabled + * + */ + static void SetReceiveIp6FilterEnabled(bool aEnabled); + /** * This static method enables/disables IPv6 forwarding. * diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index eb4f5a68b..230fae38c 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -1015,6 +1015,16 @@ void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback, voi Ip6::Ip6::SetReceiveDatagramCallback(aCallback, aCallbackContext); } +bool otGetReceiveIp6DatagramFilterEnabled(void) +{ + return Ip6::Ip6::IsReceiveIp6FilterEnabled(); +} + +void otSetReceiveIp6DatagramFilterEnabled(bool aEnabled) +{ + Ip6::Ip6::SetReceiveIp6FilterEnabled(aEnabled); +} + ThreadError otSendIp6Datagram(otMessage aMessage) { return Ip6::Ip6::HandleDatagram(*static_cast(aMessage), NULL, sThreadNetif->GetInterfaceId(),