Convert MeshHeader constructors to fail-able initializers (#1157)

This commit makes the following changes:

- It converts two of lowpan `MeshHeader` constructors to a
  fail-able initializers to handle error case where the passed-in
  argument frame or message is too short. It also updates
  `MeshForwarder` to use the new initializers instead.

- It adds new macro `IgnoreReturnValue()`. This macro is primarily
  used to indicate the intention of developer that the return value
  of the function/method can be safely ignored.
This commit is contained in:
Abtin Keshavarzian
2017-01-17 09:12:07 -08:00
committed by Jonathan Hui
parent 7831bf39ed
commit 3f243ed540
4 changed files with 119 additions and 44 deletions
+22 -6
View File
@@ -44,6 +44,7 @@
#define otDEFINE_ALIGNED_VAR(name, size, align_type) \
align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))]
/* Check the input `ERR` against zero and go to `exit` label if it is non-zero. */
#define SuccessOrExit(ERR) \
do { \
if ((ERR) != 0) { \
@@ -51,18 +52,33 @@
} \
} while (false)
#define VerifyOrExit(COND, ACTION) \
do { \
if (!(COND)) { \
ACTION; \
goto exit; \
} \
/* Verify that the `COND` is true, otherwise go to `exit` label. */
#define VerifyOrExit(COND, ACTION) \
do { \
if (!(COND)) { \
ACTION; \
goto exit; \
} \
} while (false)
/* Run the passed in statement(s) and go to `exit` label. */
#define ExitNow(...) \
do { \
__VA_ARGS__; \
goto exit; \
} while (false)
/*
* Run the `statement` and ignore the return value.
*
* This is primarily used to indicate the intention of developer that the return value of function/method can be
* safely ignored.
*
*/
#define IgnoreReturnValue(statement) \
do { \
if (statement) {} \
} while (false)
#endif // CODE_UTILS_HPP_
+54
View File
@@ -1115,5 +1115,59 @@ exit:
return (error == kThreadError_None) ? static_cast<int>(compressedLength) : -1;
}
ThreadError MeshHeader::Init(const uint8_t *aFrame, uint8_t aFrameLength)
{
ThreadError error = kThreadError_None;
VerifyOrExit(aFrameLength >= 1, error = kThreadError_Failed);
mDispatchHopsLeft = *aFrame++;
aFrameLength--;
if (IsDeepHopsLeftField())
{
VerifyOrExit(aFrameLength >= 1, error = kThreadError_Failed);
mDeepHopsLeft = *aFrame++;
aFrameLength--;
}
else
{
mDeepHopsLeft = 0;
}
VerifyOrExit(aFrameLength >= sizeof(mAddress), error = kThreadError_Failed);
memcpy(&mAddress, aFrame, sizeof(mAddress));
exit:
return error;
}
ThreadError MeshHeader::Init(const Message &aMessage)
{
ThreadError error = kThreadError_None;
uint16_t offset = 0;
uint16_t bytesRead;
bytesRead = aMessage.Read(offset, sizeof(mDispatchHopsLeft), &mDispatchHopsLeft);
VerifyOrExit(bytesRead == sizeof(mDispatchHopsLeft), error = kThreadError_Failed);
offset += bytesRead;
if (IsDeepHopsLeftField())
{
bytesRead = aMessage.Read(offset, sizeof(mDeepHopsLeft), &mDeepHopsLeft);
VerifyOrExit(bytesRead == sizeof(mDeepHopsLeft), error = kThreadError_Failed);
offset += bytesRead;
}
else
{
mDeepHopsLeft = 0;
}
bytesRead = aMessage.Read(offset, sizeof(mAddress), &mAddress);
VerifyOrExit(bytesRead == sizeof(mAddress), error = kThreadError_Failed);
exit:
return error;
}
} // namespace Lowpan
} // namespace Thread
+23 -29
View File
@@ -232,41 +232,35 @@ public:
*/
MeshHeader(void) { memset(this, 0, sizeof(*this)); }
/**
* Mesh Header constructor that takes frame @p aFrame as a parameter.
*
* @param[in] aFrame The pointer to the frame.
*
*/
MeshHeader(const uint8_t *aFrame) {
mDispatchHopsLeft = *aFrame++;
mDeepHopsLeft = IsDeepHopsLeftField() ? *aFrame++ : 0;
memcpy(&mAddress, aFrame, sizeof(mAddress));
}
/**
* Mesh Header constructor that takes message object @p aMessage as a parameter.
*
* @param[in] aMessage The message object.
*
*/
MeshHeader(const Message &aMessage) {
aMessage.Read(0, sizeof(mDispatchHopsLeft), &mDispatchHopsLeft);
if (IsDeepHopsLeftField()) {
aMessage.Read(1, sizeof(mDeepHopsLeft) + sizeof(mAddress), &mDeepHopsLeft);
}
else {
aMessage.Read(1, sizeof(mAddress), &mAddress);
}
}
/**
* This method initializes the header.
*
*/
void Init(void) { mDispatchHopsLeft = kDispatch | kSourceShort | kDestinationShort; }
/**
* This method initializes the mesh header from a frame @p aFrame.
*
* @param[in] aFrame The pointer to the frame.
* @param[in] aFrameLength The length of the frame.
*
* @retval kThreadError_None Mesh Header initialized successfully.
* @retval kThreadError_Failed Mesh header could not be initialized from @p aFrame (e.g., frame not long enough).
*
*/
ThreadError Init(const uint8_t *aFrame, uint8_t aFrameLength);
/**
* This method initializes the mesh header from a message object @p aMessage.
*
* @param[in] aMessage The message object.
*
* @retval kThreadError_None Mesh Header initialized successfully.
* @retval kThreadError_Failed Mesh header could not be initialized from @ aMessage(e.g., not long enough).
*
*/
ThreadError Init(const Message &aMessage);
/**
* This method indicates whether or not the header is a Mesh Header.
*
+20 -9
View File
@@ -394,13 +394,16 @@ ThreadError MeshForwarder::SendMessage(Message &aMessage)
{
ThreadError error = kThreadError_None;
Neighbor *neighbor;
Ip6::Header ip6Header;
uint8_t numChildren;
Child *children;
switch (aMessage.GetType())
{
case Message::kTypeIp6:
{
Ip6::Header ip6Header;
aMessage.Read(0, sizeof(ip6Header), &ip6Header);
if (!memcmp(&ip6Header.GetDestination(), mMle.GetLinkLocalAllThreadNodesAddress(),
@@ -443,10 +446,13 @@ ThreadError MeshForwarder::SendMessage(Message &aMessage)
}
break;
}
case Message::kType6lowpan:
{
Lowpan::MeshHeader meshHeader(aMessage);
Lowpan::MeshHeader meshHeader;
IgnoreReturnValue(meshHeader.Init(aMessage));
if ((neighbor = mMle.GetNeighbor(meshHeader.GetDestination())) != NULL &&
(neighbor->mMode & Mle::ModeTlv::kModeRxOnWhenIdle) == 0)
@@ -573,8 +579,9 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
case Message::kType6lowpan:
{
Lowpan::MeshHeader meshHeader(*message);
Lowpan::MeshHeader meshHeader;
IgnoreReturnValue(meshHeader.Init(*message));
mAddMeshHeader = true;
mMeshDest = meshHeader.GetDestination();
mMeshSource = meshHeader.GetSource();
@@ -594,13 +601,16 @@ exit:
return message;
}
ThreadError MeshForwarder::UpdateMeshRoute(Message &aMessage)
{
ThreadError error = kThreadError_None;
Lowpan::MeshHeader meshHeader(aMessage);
Lowpan::MeshHeader meshHeader;
Neighbor *neighbor;
uint16_t nextHop;
IgnoreReturnValue(meshHeader.Init(aMessage));
nextHop = mMle.GetNextHop(meshHeader.GetDestination());
if (nextHop != Mac::kShortAddrInvalid)
@@ -1637,10 +1647,10 @@ void MeshForwarder::HandleMesh(uint8_t *aFrame, uint8_t aFrameLength, const Mac:
Message *message = NULL;
Mac::Address meshDest;
Mac::Address meshSource;
Lowpan::MeshHeader meshHeader(aFrame);
Lowpan::MeshHeader meshHeader;
// Length Check
VerifyOrExit(meshHeader.GetHeaderLength() <= aFrameLength, error = kThreadError_Drop);
// Check the mesh header
VerifyOrExit(meshHeader.Init(aFrame, aFrameLength) == kThreadError_None, error = kThreadError_Drop);
// Security Check: only process Mesh Header frames that had security enabled.
VerifyOrExit(aMessageInfo.mLinkSecurity && meshHeader.IsValid(), error = kThreadError_Security);
@@ -1705,10 +1715,11 @@ ThreadError MeshForwarder::CheckReachability(uint8_t *aFrame, uint8_t aFrameLeng
{
ThreadError error = kThreadError_None;
Ip6::Header ip6Header;
Lowpan::MeshHeader meshHeader(aFrame);
Lowpan::MeshHeader meshHeader;
VerifyOrExit(meshHeader.Init(aFrame, aFrameLength) == kThreadError_None, error = kThreadError_Drop);
// skip mesh header
VerifyOrExit(meshHeader.GetHeaderLength() <= aFrameLength, error = kThreadError_Drop);
aFrame += meshHeader.GetHeaderLength();
aFrameLength -= meshHeader.GetHeaderLength();