diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index b15ff3b14..9cd2108ba 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -1242,12 +1242,11 @@ otError MeshForwarder::GetFramePriority(const uint8_t * aFrame, const Mac::Address &aMacDest, Message::Priority & aPriority) { - otError error = OT_ERROR_NONE; - Ip6::Header ip6Header; - Ip6::Udp::Header udpHeader; - Ip6::Icmp::Header icmpHeader; - uint8_t headerLength; - bool nextHeaderCompressed; + otError error = OT_ERROR_NONE; + Ip6::Header ip6Header; + uint16_t dstPort; + uint8_t headerLength; + bool nextHeaderCompressed; SuccessOrExit(error = DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, ip6Header, headerLength, nextHeaderCompressed)); @@ -1256,35 +1255,46 @@ otError MeshForwarder::GetFramePriority(const uint8_t * aFrame, aFrame += headerLength; aFrameLength -= headerLength; - if (ip6Header.GetNextHeader() == Ip6::kProtoIcmp6 && aFrameLength) + switch (ip6Header.GetNextHeader()) { - // Just check the first byte which is an ICMPv6 type. - memcpy(&icmpHeader, aFrame, sizeof(icmpHeader.mType)); + case Ip6::kProtoIcmp6: + + VerifyOrExit(aFrameLength >= sizeof(Ip6::Icmp::Header), error = OT_ERROR_PARSE); // Only ICMPv6 error messages are prioritized. - if (icmpHeader.IsError()) + if (reinterpret_cast(aFrame)->IsError()) { aPriority = Message::kPriorityNet; } - ExitNow(); - } + break; - VerifyOrExit(ip6Header.GetNextHeader() == Ip6::kProtoUdp, OT_NOOP); + case Ip6::kProtoUdp: - if (nextHeaderCompressed) - { - VerifyOrExit(Get().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0, OT_NOOP); - } - else - { - VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = OT_ERROR_PARSE); - memcpy(&udpHeader, aFrame, sizeof(Ip6::Udp::Header)); - } + if (nextHeaderCompressed) + { + Ip6::Udp::Header udpHeader; - if (udpHeader.GetDestinationPort() == Mle::kUdpPort || udpHeader.GetDestinationPort() == kCoapUdpPort) - { - aPriority = Message::kPriorityNet; + VerifyOrExit(Get().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0, + error = OT_ERROR_PARSE); + + dstPort = udpHeader.GetDestinationPort(); + } + else + { + VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = OT_ERROR_PARSE); + dstPort = reinterpret_cast(aFrame)->GetDestinationPort(); + } + + if ((dstPort == Mle::kUdpPort) || (dstPort == kCoapUdpPort)) + { + aPriority = Message::kPriorityNet; + } + + break; + + default: + break; } exit: diff --git a/tests/unit/test_toolchain.cpp b/tests/unit/test_toolchain.cpp index c43ce1458..5e5da5805 100644 --- a/tests/unit/test_toolchain.cpp +++ b/tests/unit/test_toolchain.cpp @@ -41,7 +41,7 @@ uint32_t otNetifAddress_offset_mNext_c(); otNetifAddress CreateNetif_c(); } -void test_packed1() +void test_packed1(void) { OT_TOOL_PACKED_BEGIN struct packed_t @@ -56,7 +56,7 @@ void test_packed1() VerifyOrQuit(sizeof(packed_t) == 7, "Toolchain::OT_TOOL_PACKED failed 1"); } -void test_packed2() +void test_packed2(void) { OT_TOOL_PACKED_BEGIN struct packed_t @@ -70,7 +70,7 @@ void test_packed2() VerifyOrQuit(sizeof(packed_t) == 4, "Toolchain::OT_TOOL_PACKED failed 2"); } -void test_packed_union() +void test_packed_union(void) { typedef struct { @@ -93,7 +93,7 @@ void test_packed_union() VerifyOrQuit(sizeof(packed_t) == 5, "Toolchain::OT_TOOL_PACKED failed 3"); } -void test_packed_enum() +void test_packed_enum(void) { ot::Neighbor neighbor; neighbor.SetState(ot::Neighbor::kStateValid); @@ -102,18 +102,68 @@ void test_packed_enum() VerifyOrQuit(neighbor.GetState() == ot::Neighbor::kStateValid, "Toolchain::OT_TOOL_PACKED failed 4"); } -void test_addr_sizes() +void test_addr_sizes(void) { VerifyOrQuit(offsetof(otNetifAddress, mNext) == otNetifAddress_offset_mNext_c(), "mNext should offset the same in C & C++"); VerifyOrQuit(sizeof(otNetifAddress) == otNetifAddress_Size_c(), "otNetifAddress should the same in C & C++"); } -void test_addr_bitfield() +void test_addr_bitfield(void) { VerifyOrQuit(CreateNetif_c().mScopeOverrideValid == true, "Toolchain::test_addr_size_cpp"); } +void test_packed_alignment(void) +{ + OT_TOOL_PACKED_BEGIN + struct PackedStruct + { + uint32_t mUint32; + uint8_t mByte; + uint16_t mUint16; + } OT_TOOL_PACKED_END; + + PackedStruct packedStruct; + PackedStruct packedStructCopy; + const uint8_t *packedStructBytes = reinterpret_cast(&packedStruct); + uint8_t buffer[sizeof(PackedStruct) * 2 + 1]; + + VerifyOrQuit(sizeof(PackedStruct) == 7, "Toolchain::OT_TOOL_PACKED failed"); + + packedStruct.mUint32 = 0x12345678; + packedStruct.mByte = 0xfe; + packedStruct.mUint16 = 0xabcd; + + for (uint16_t start = 0; start < sizeof(PackedStruct); start++) + { + uint8_t *ptr = &buffer[start]; + + memset(buffer, 0, sizeof(buffer)); + + *reinterpret_cast(ptr) = packedStruct; + + for (uint16_t i = 0; i < start; i++) + { + VerifyOrQuit(buffer[i] == 0, "Toolchain::OT_TOOL_PACKED alignment failed - pre-size write"); + } + + VerifyOrQuit(memcmp(ptr, packedStructBytes, sizeof(PackedStruct)) == 0, + "Toolchain::OT_TOOL_PACKED alignment failed"); + + for (uint16_t i = start + sizeof(packedStruct); i < sizeof(buffer); i++) + { + VerifyOrQuit(buffer[i] == 0, "Toolchain::OT_TOOL_PACKED alignment failed - post-size write"); + } + + memset(&packedStructCopy, 0, sizeof(PackedStruct)); + packedStructCopy = *reinterpret_cast(ptr); + + VerifyOrQuit(memcmp(&packedStructCopy, &packedStruct, sizeof(PackedStruct)) == 0, + "Toolchain::OT_TOOL_PACKED failed - read error"); + } +} + void TestToolchain(void) { test_packed1(); @@ -122,6 +172,7 @@ void TestToolchain(void) test_packed_enum(); test_addr_sizes(); test_addr_bitfield(); + test_packed_alignment(); } int main(void)