[ip6] clean up return values for otIp6Send() (#3751)

- Return OT_ERROR_PARSE when encountering mal-formatted headers.
- Return OT_ERROR_NO_ROUTE when there is no route to host.
- Document possible return values for `otIp6Send()`.
This commit is contained in:
Jonathan Hui
2019-04-12 08:48:35 -07:00
committed by GitHub
parent b7b085c9f9
commit bd517c9bf2
7 changed files with 44 additions and 25 deletions
+9
View File
@@ -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);
+9 -8
View File
@@ -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;
+13 -4
View File
@@ -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,
+1 -1
View File
@@ -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)
{
+1 -1
View File
@@ -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();
+3 -3
View File
@@ -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:
+8 -8
View File
@@ -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<TypeListTlv *>(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_DROP);
VerifyOrExit((static_cast<TypeListTlv *>(&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<TypeListTlv *>(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_DROP);
VerifyOrExit((static_cast<TypeListTlv *>(&networkDiagnosticTlv)->IsValid()), error = OT_ERROR_PARSE);
VerifyOrExit((message = Get<Coap::Coap>().NewMessage()) != NULL, error = OT_ERROR_NO_BUFS);