diff --git a/src/core/coap/coap_server.cpp b/src/core/coap/coap_server.cpp index b8edbd4ef..ede57e841 100644 --- a/src/core/coap/coap_server.cpp +++ b/src/core/coap/coap_server.cpp @@ -50,6 +50,7 @@ Server::Server(Ip6::Netif &aNetif, uint16_t aPort, SenderFunction aSender, Recei { mPort = aPort; mResources = NULL; + mInterceptor = NULL; } ThreadError Server::Start(void) @@ -144,6 +145,11 @@ void Server::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &a const Header::Option *coapOption; Message *response; + if (mInterceptor != NULL) + { + SuccessOrExit(mInterceptor(aMessage, aMessageInfo)); + } + SuccessOrExit(header.FromMessage(aMessage, 0)); aMessage.MoveOffset(header.GetLength()); diff --git a/src/core/coap/coap_server.hpp b/src/core/coap/coap_server.hpp index bac0d5055..9542b6c9e 100644 --- a/src/core/coap/coap_server.hpp +++ b/src/core/coap/coap_server.hpp @@ -287,6 +287,20 @@ private: class Server : public CoapBase { public: + /** + * This function pointer is called before CoAP server processing a CoAP packets. + * + * @param[in] aMessage A reference to the message. + @ @param[in] aMessageInfo A reference to the message info associated with @p aMessage. + * + * @retval kThreadError_None Server should continue processing this message, other + * return values indicates the server should stop processing + * this message. + * @retval kThreadError_Security The message does not comply with security rules. + * + */ + typedef ThreadError(* Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + /** * This constructor initializes the object. * @@ -371,6 +385,16 @@ public: const MessageQueue &GetCachedResponses(void) const { return mResponsesQueue.GetResponses(); } + /** + * This method sets interceptor to be called before processing a CoAP packet. + * + * @param[in] aInterceptor A pointer to the interceptor. + * + */ + void SetInterceptor(Interceptor aInterpreter) { + mInterceptor = aInterpreter; + } + protected: void ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); @@ -386,6 +410,7 @@ private: uint16_t mPort; Resource *mResources; + Interceptor mInterceptor; ResponsesQueue mResponsesQueue; }; diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index 3495f79c8..3ffdfa63c 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -111,6 +111,7 @@ ThreadNetif::ThreadNetif(Ip6::Ip6 &aIp6): { mKeyManager.SetMasterKey(kThreadMasterKey, sizeof(kThreadMasterKey)); + mCoapServer.SetInterceptor(&ThreadNetif::TmfFilter); } ThreadError ThreadNetif::Up(void) @@ -182,6 +183,27 @@ exit: return error; } +ThreadError ThreadNetif::TmfFilter(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +{ + ThreadError error = kThreadError_None; + + // A TMF message must comply one of the following rules: + // 1. Source address is RLOC or ALOC, and destination address is RLOC, ALOC or realm-local multicast. + // 2. Both source and destination addresses are link-local.(for Joiner Entrust) + VerifyOrExit(((aMessageInfo.GetPeerAddr().IsRoutingLocator() || + aMessageInfo.GetPeerAddr().IsAnycastRoutingLocator()) && + (aMessageInfo.GetSockAddr().IsRoutingLocator() || + aMessageInfo.GetSockAddr().IsAnycastRoutingLocator() || + aMessageInfo.GetSockAddr().IsRealmLocalMulticast())) || + (aMessageInfo.GetPeerAddr().IsLinkLocal() && + aMessageInfo.GetSockAddr().IsLinkLocal()), + error = kThreadError_Security); + +exit: + (void)aMessage; + return error; +} + otInstance *ThreadNetif::GetInstance(void) { return otInstanceFromThreadNetif(this); diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index f25d9c844..6e7347e2b 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -338,6 +338,8 @@ public: otInstance *GetInstance(void); private: + static ThreadError TmfFilter(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + Coap::Server mCoapServer; Coap::Client mCoapClient; AddressResolver mAddressResolver;