diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index 7bf32a956..ea348961b 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -409,9 +409,18 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled); /** * This function sends an IPv6 datagram via the Thread interface. * + * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when + * processing is complete, including when a value other than `OT_ERROR_NONE` is returned. + * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aMessage A pointer to the message buffer containing the IPv6 datagram. * + * @retval OT_ERROR_NONE Successfully processed the message. + * @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing rules. + * @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram. + * @retval OT_ERROR_NO_ROUTE No route to host. + * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message. + * */ otError otIp6Send(otInstance *aInstance, otMessage *aMessage); diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 0e2c14e62..fa685121d 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -215,6 +215,7 @@ otError Ip6::AddMplOption(Message &aMessage, Header &aHeader) SuccessOrExit(error = aMessage.Prepend(&hbhHeader, sizeof(hbhHeader))); aHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(hbhHeader) + sizeof(mplOption)); aHeader.SetNextHeader(kProtoHopOpts); + exit: return error; } @@ -554,17 +555,17 @@ otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aForward) uint16_t endOffset; VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(hbhHeader), &hbhHeader) == sizeof(hbhHeader), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); endOffset = aMessage.GetOffset() + (hbhHeader.GetLength() + 1) * 8; - VerifyOrExit(endOffset <= aMessage.GetLength(), error = OT_ERROR_DROP); + VerifyOrExit(endOffset <= aMessage.GetLength(), error = OT_ERROR_PARSE); aMessage.MoveOffset(sizeof(optionHeader)); while (aMessage.GetOffset() < endOffset) { VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(optionHeader), &optionHeader) == sizeof(optionHeader), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); if (optionHeader.GetType() == OptionPad1::kType) { @@ -573,7 +574,7 @@ otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aForward) } VerifyOrExit(aMessage.GetOffset() + sizeof(optionHeader) + optionHeader.GetLength() <= endOffset, - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); switch (optionHeader.GetType()) { @@ -615,7 +616,7 @@ otError Ip6::HandleFragment(Message &aMessage) FragmentHeader fragmentHeader; VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(fragmentHeader), &fragmentHeader) == sizeof(fragmentHeader), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); VerifyOrExit(fragmentHeader.GetOffset() == 0 && fragmentHeader.IsMoreFlagSet() == false, error = OT_ERROR_DROP); @@ -637,7 +638,7 @@ otError Ip6::HandleExtensionHeaders(Message &aMessage, while (aReceive == true || aNextHeader == kProtoHopOpts) { VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(extHeader), &extHeader) == sizeof(extHeader), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); switch (aNextHeader) { @@ -696,7 +697,7 @@ otError Ip6::ProcessReceiveCallback(const Message & aMessage, otError error = OT_ERROR_NONE; Message *messageCopy = NULL; - VerifyOrExit(aFromNcpHost == false, error = OT_ERROR_DROP); + VerifyOrExit(aFromNcpHost == false, error = OT_ERROR_NO_ROUTE); VerifyOrExit(mReceiveIp6DatagramCallback != NULL, error = OT_ERROR_NO_ROUTE); if (mIsReceiveIp6FilterEnabled) @@ -716,7 +717,7 @@ otError Ip6::ProcessReceiveCallback(const Message & aMessage, aMessage.Read(aMessage.GetOffset(), sizeof(icmp), &icmp); // do not pass ICMP Echo Request messages - VerifyOrExit(icmp.GetType() != IcmpHeader::kTypeEchoRequest, error = OT_ERROR_NO_ROUTE); + VerifyOrExit(icmp.GetType() != IcmpHeader::kTypeEchoRequest, error = OT_ERROR_DROP); } break; diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index e78e52d70..a9b3bec79 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -183,11 +183,17 @@ public: /** * This method sends a raw IPv6 datagram with a fully formed IPv6 header. * + * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when + * processing is complete, including when a value other than `OT_ERROR_NONE` is returned. + * * @param[in] aMessage A reference to the message. * @param[in] aInterfaceId The interface identifier of the network interface that received the message. * - * @retval OT_ERROR_NONE Successfully processed the message. - * @retval OT_ERROR_DROP Message processing failed and the message should be dropped. + * @retval OT_ERROR_NONE Successfully processed the message. + * @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing rules. + * @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram. + * @retval OT_ERROR_NO_ROUTE No route to host. + * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message. * */ otError SendRaw(Message &aMessage, int8_t aInterfaceId); @@ -201,8 +207,11 @@ public: * @param[in] aLinkMessageInfo A pointer to link-specific message information. * @param[in] aFromNcpHost TRUE if the message was submitted by the NCP host, FALSE otherwise. * - * @retval OT_ERROR_NONE Successfully processed the message. - * @retval OT_ERROR_DROP Message processing failed and the message should be dropped. + * @retval OT_ERROR_NONE Successfully processed the message. + * @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing rules. + * @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram. + * @retval OT_ERROR_NO_ROUTE No route to host. + * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message. * */ otError HandleDatagram(Message & aMessage, diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp index bde8c0f4f..64270a973 100644 --- a/src/core/net/ip6_mpl.cpp +++ b/src/core/net/ip6_mpl.cpp @@ -300,7 +300,7 @@ otError Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsO VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(option), &option) >= OptionMpl::kMinLength && (option.GetSeedIdLength() == OptionMpl::kSeedIdLength0 || option.GetSeedIdLength() == OptionMpl::kSeedIdLength2), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); if (option.GetSeedIdLength() == OptionMpl::kSeedIdLength0) { diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 4da73e537..b59224254 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -1309,7 +1309,7 @@ void MeshForwarder::HandleFragment(uint8_t * aFrame, int headerLength; // Check the fragment header - VerifyOrExit(fragmentHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_DROP); + VerifyOrExit(fragmentHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_PARSE); aFrame += fragmentHeader.GetHeaderLength(); aFrameLength -= fragmentHeader.GetHeaderLength(); diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 5ae12d323..08c82b263 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -924,7 +924,7 @@ void MeshForwarder::HandleMesh(uint8_t * aFrame, Lowpan::MeshHeader meshHeader; // Check the mesh header - VerifyOrExit(meshHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_DROP); + VerifyOrExit(meshHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_PARSE); // Security Check: only process Mesh Header frames that had security enabled. VerifyOrExit(aLinkInfo.mLinkSecurity && meshHeader.IsValid(), error = OT_ERROR_SECURITY); @@ -1212,13 +1212,13 @@ otError MeshForwarder::GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, ui else { // ServiceTLV without ServerTLV? Can't forward packet anywhere. - ExitNow(error = OT_ERROR_DROP); + ExitNow(error = OT_ERROR_NO_ROUTE); } } else { // Unknown service, can't forward - ExitNow(error = OT_ERROR_DROP); + ExitNow(error = OT_ERROR_NO_ROUTE); } exit: diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index e4871f3a5..ce78314af 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -290,7 +290,7 @@ otError NetworkDiagnostic::FillRequestedTlvs(Message & aRequest, for (uint32_t i = 0; i < aNetworkDiagnosticTlv.GetLength(); i++) { - VerifyOrExit(aRequest.Read(offset, sizeof(type), &type) == sizeof(type), error = OT_ERROR_DROP); + VerifyOrExit(aRequest.Read(offset, sizeof(type), &type) == sizeof(type), error = OT_ERROR_PARSE); otLogInfoNetDiag("Type %d", type); @@ -454,7 +454,7 @@ otError NetworkDiagnostic::FillRequestedTlvs(Message & aRequest, } default: - ExitNow(error = OT_ERROR_DROP); + ExitNow(error = OT_ERROR_PARSE); } offset += sizeof(type); @@ -483,11 +483,11 @@ void NetworkDiagnostic::HandleDiagnosticGetQuery(Coap::Message &aMessage, const VerifyOrExit((aMessage.Read(aMessage.GetOffset(), sizeof(NetworkDiagnosticTlv), &networkDiagnosticTlv) == sizeof(NetworkDiagnosticTlv)), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); - VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = OT_ERROR_DROP); + VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = OT_ERROR_PARSE); - VerifyOrExit((static_cast(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_DROP); + VerifyOrExit((static_cast(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_PARSE); // DIAG_GET.qry may be sent as a confirmable message. if (aMessage.GetType() == OT_COAP_TYPE_CONFIRMABLE) @@ -556,11 +556,11 @@ void NetworkDiagnostic::HandleDiagnosticGetRequest(Coap::Message &aMessage, cons VerifyOrExit((aMessage.Read(aMessage.GetOffset(), sizeof(NetworkDiagnosticTlv), &networkDiagnosticTlv) == sizeof(NetworkDiagnosticTlv)), - error = OT_ERROR_DROP); + error = OT_ERROR_PARSE); - VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = OT_ERROR_DROP); + VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = OT_ERROR_PARSE); - VerifyOrExit((static_cast(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_DROP); + VerifyOrExit((static_cast(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_PARSE); VerifyOrExit((message = Get().NewMessage()) != NULL, error = OT_ERROR_NO_BUFS);