From e5d15f19117e764ba8cda7557cd05edf389d06a1 Mon Sep 17 00:00:00 2001 From: Giedrius Date: Wed, 29 Mar 2017 15:54:43 +0300 Subject: [PATCH] CoAP option update (#1523) * Do not drop CoAP requests with unknown options If packets are dropped due to unrecognized options, then it should be done according to RFC7252 Section 5.4.1., otherwise leave it for the user. * Implement CoAP Header GetFirstOption * Implement in Header * Add to CoAP API * Use in code * Remove CoAP Header GetCurrentOption * Correction in the comments * Initialize CoAP Header before parsing --- include/openthread/coap.h | 7 ++++--- src/core/api/coap_api.cpp | 4 ++-- src/core/coap/coap_header.cpp | 29 +++++++++++++++++++++++++++-- src/core/coap/coap_header.hpp | 6 +++--- src/core/coap/coap_server.cpp | 7 ++----- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/include/openthread/coap.h b/include/openthread/coap.h index 8afb34de7..0d341d62e 100644 --- a/include/openthread/coap.h +++ b/include/openthread/coap.h @@ -136,6 +136,7 @@ typedef struct otCoapHeader } mHeader; ///< The CoAP header encoding uint8_t mHeaderLength; ///< The CoAP header length (bytes) uint16_t mOptionLast; ///< The last CoAP Option Number value + uint16_t mFirstOptionOffset; ///< The byte offset for the first CoAP Option uint16_t mNextOptionOffset; ///< The byte offset for the next CoAP Option otCoapOption mOption; ///< A structure representing the current CoAP Option. } otCoapHeader; @@ -344,14 +345,14 @@ uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader); const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader); /** - * This function returns a pointer to the current option. + * This function returns a pointer to the first option. * * @param[in] aHeader A pointer to the CoAP header. * - * @returns A pointer to the current option. If no option is present NULL pointer is returned. + * @returns A pointer to the first option. If no option is present NULL pointer is returned. * */ -const otCoapOption *otCoapHeaderGetCurrentOption(const otCoapHeader *aHeader); +const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader); /** * This function returns a pointer to the next option. diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp index c459208ef..beacdd5d9 100644 --- a/src/core/api/coap_api.cpp +++ b/src/core/api/coap_api.cpp @@ -116,9 +116,9 @@ const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader) return static_cast(aHeader)->GetToken(); } -const otCoapOption *otCoapHeaderGetCurrentOption(const otCoapHeader *aHeader) +const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader) { - return static_cast(static_cast(aHeader)->GetCurrentOption()); + return static_cast(static_cast(aHeader)->GetFirstOption()); } const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader) diff --git a/src/core/coap/coap_header.cpp b/src/core/coap/coap_header.cpp index 1267bbce7..1d9269dbf 100644 --- a/src/core/coap/coap_header.cpp +++ b/src/core/coap/coap_header.cpp @@ -46,6 +46,7 @@ void Header::Init(void) { mHeaderLength = kMinHeaderLength; mOptionLast = 0; + mFirstOptionOffset = 0; mNextOptionOffset = 0; memset(&mOption, 0, sizeof(mOption)); memset(&mHeader, 0, sizeof(mHeader)); @@ -71,6 +72,8 @@ ThreadError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) length -= aMetadataSize; + Init(); + VerifyOrExit(length >= kTokenOffset, error = kThreadError_Parse); aMessage.Read(offset, kTokenOffset, mHeader.mBytes); mHeaderLength = kTokenOffset; @@ -96,6 +99,11 @@ ThreadError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) ExitNow(error = kThreadError_None); } + if (firstOption) + { + mFirstOptionOffset = mHeaderLength; + } + optionDelta = mHeader.mBytes[mHeaderLength] >> 4; optionLength = mHeader.mBytes[mHeaderLength] & 0xf; mHeaderLength += sizeof(uint8_t); @@ -173,6 +181,13 @@ ThreadError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) } exit: + + // In case any step failed, prevent access to corrupt Option + if (error != kThreadError_None) + { + mFirstOptionOffset = 0; + } + return error; } @@ -328,9 +343,19 @@ ThreadError Header::AppendUriQueryOption(const char *aUriQuery) return AppendOption(coapOption); } -const Header::Option *Header::GetCurrentOption(void) const +const Header::Option *Header::GetFirstOption(void) { - return static_cast(&mOption); + const Option *rval = NULL; + + VerifyOrExit(mFirstOptionOffset > 0,); + + memset(&mOption, 0, sizeof(mOption)); + mNextOptionOffset = mFirstOptionOffset; + + rval = GetNextOption(); + +exit: + return rval; } const Header::Option *Header::GetNextOption(void) diff --git a/src/core/coap/coap_header.hpp b/src/core/coap/coap_header.hpp index 8af76aab5..35245eea2 100644 --- a/src/core/coap/coap_header.hpp +++ b/src/core/coap/coap_header.hpp @@ -340,12 +340,12 @@ public: ThreadError AppendUriQueryOption(const char *aUriQuery); /** - * This method returns a pointer to the current option. + * This method returns a pointer to the first option. * - * @returns A pointer to the current option. + * @returns A pointer to the first option. * */ - const Option *GetCurrentOption(void) const; + const Option *GetFirstOption(void); /** * This method returns a pointer to the next option. diff --git a/src/core/coap/coap_server.cpp b/src/core/coap/coap_server.cpp index 0736a9ae3..571fa935a 100644 --- a/src/core/coap/coap_server.cpp +++ b/src/core/coap/coap_server.cpp @@ -173,7 +173,7 @@ void Server::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &a break; } - coapOption = header.GetCurrentOption(); + coapOption = header.GetFirstOption(); while (coapOption != NULL) { @@ -191,11 +191,8 @@ void Server::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &a curUriPath += coapOption->mLength; break; - case kCoapOptionContentFormat: - break; - default: - ExitNow(); + break; } coapOption = header.GetNextOption();