diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index 5c1fa365c..50ad85adf 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -58,18 +58,24 @@ void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl) // Sequence Number length += kDsnSize; - // Destination PAN + Address + // Destination PAN + if (IsDstPanIdPresent(aFcf)) + { + length += sizeof(PanId); + } + + // Destination Address switch (aFcf & kFcfDstAddrMask) { case kFcfDstAddrNone: break; case kFcfDstAddrShort: - length += sizeof(PanId) + sizeof(ShortAddress); + length += sizeof(ShortAddress); break; case kFcfDstAddrExt: - length += sizeof(PanId) + sizeof(ExtAddress); + length += sizeof(ExtAddress); break; default: @@ -193,6 +199,38 @@ exit: return index; } +bool Frame::IsDstPanIdPresent(uint16_t aFcf) +{ + bool present = true; + +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + if (IsVersion2015(aFcf)) + { + switch (aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask | kFcfPanidCompression)) + { + case (kFcfDstAddrNone | kFcfSrcAddrNone): + case (kFcfDstAddrExt | kFcfSrcAddrNone | kFcfPanidCompression): + case (kFcfDstAddrShort | kFcfSrcAddrNone | kFcfPanidCompression): + case (kFcfDstAddrNone | kFcfSrcAddrExt): + case (kFcfDstAddrNone | kFcfSrcAddrShort): + case (kFcfDstAddrNone | kFcfSrcAddrExt | kFcfPanidCompression): + case (kFcfDstAddrNone | kFcfSrcAddrShort | kFcfPanidCompression): + case (kFcfDstAddrExt | kFcfSrcAddrExt | kFcfPanidCompression): + present = false; + break; + default: + break; + } + } + else +#endif + { + present = IsDstAddrPresent(aFcf); + } + + return present; +} + otError Frame::GetDstPanId(PanId &aPanId) const { otError error = OT_ERROR_NONE; @@ -321,7 +359,7 @@ bool Frame::IsSrcPanIdPresent(uint16_t aFcf) const // Dest Pan ID: Present // Src Pan ID: Not Present // Pan ID Compression: 0 - if ((aFcf & kFcfFrameVersionMask) != kFcfFrameVersion2015 || (aFcf & kFcfDstAddrMask) != kFcfDstAddrExt || + if (!IsVersion2015(aFcf) || (aFcf & kFcfDstAddrMask) != kFcfDstAddrExt || (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrExt) #endif { @@ -364,15 +402,21 @@ uint8_t Frame::FindSrcAddrIndex(void) const // Frame Control Field and Sequence Number index += kFcfSize + kDsnSize; - // Destination PAN + Address + // Destination PAN + if (IsDstPanIdPresent(fcf)) + { + index += sizeof(PanId); + } + + // Destination Address switch (fcf & kFcfDstAddrMask) { case kFcfDstAddrShort: - index += sizeof(PanId) + sizeof(ShortAddress); + index += sizeof(ShortAddress); break; case kFcfDstAddrExt: - index += sizeof(PanId) + sizeof(ExtAddress); + index += sizeof(ExtAddress); break; } @@ -450,45 +494,35 @@ void Frame::SetSrcAddr(const Address &aAddress) } } +otError Frame::GetSecurityControlField(uint8_t &aSecurityControlField) const +{ + otError error = OT_ERROR_NONE; + uint8_t index = FindSecurityHeaderIndex(); + + VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE); + + aSecurityControlField = GetPsdu()[index]; + +exit: + return error; +} + +void Frame::SetSecurityControlField(uint8_t aSecurityControlField) +{ + uint8_t index = FindSecurityHeaderIndex(); + + OT_ASSERT(index != kInvalidIndex); + + GetPsdu()[index] = aSecurityControlField; +} + uint8_t Frame::FindSecurityHeaderIndex(void) const { - uint8_t index = 0; - uint16_t fcf = GetFrameControlField(); + uint8_t index; - VerifyOrExit((fcf & kFcfSecurityEnabled) != 0, index = kInvalidIndex); - - // Frame Control Field and Sequence Number - index += kFcfSize + kDsnSize; - - // Destination PAN + Address - switch (fcf & kFcfDstAddrMask) - { - case kFcfDstAddrShort: - index += sizeof(PanId) + sizeof(ShortAddress); - break; - - case kFcfDstAddrExt: - index += sizeof(PanId) + sizeof(ExtAddress); - break; - } - - // Source PAN - if (IsSrcPanIdPresent(fcf)) - { - index += sizeof(PanId); - } - - // Source Address - switch (fcf & kFcfSrcAddrMask) - { - case kFcfSrcAddrShort: - index += sizeof(ShortAddress); - break; - - case kFcfSrcAddrExt: - index += sizeof(ExtAddress); - break; - } + VerifyOrExit(kFcfSize < GetLength(), index = kInvalidIndex); + VerifyOrExit(GetSecurityEnabled(), index = kInvalidIndex); + index = SkipAddrFieldIndex(); exit: return index; @@ -734,34 +768,75 @@ void Frame::SetPayloadLength(uint16_t aLength) uint8_t Frame::SkipSecurityHeaderIndex(void) const { - uint8_t index = 0; + uint8_t index = SkipAddrFieldIndex(); uint16_t fcf; - // Frame Control - index += kFcfSize; - // Sequence Number - index += kDsnSize; - - VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex); - + VerifyOrExit(index != kInvalidIndex, OT_NOOP); fcf = GetFrameControlField(); - // Destination PAN + Address + // Security Control + Frame Counter + Key Identifier + if ((fcf & kFcfSecurityEnabled) != 0) + { + VerifyOrExit(index < GetPsduLength(), index = kInvalidIndex); + uint8_t securityControl = *(GetPsdu() + index); + + index += kSecurityControlSize + kFrameCounterSize; + + switch (securityControl & kKeyIdModeMask) + { + case kKeyIdMode0: + index += kKeySourceSizeMode0; + break; + + case kKeyIdMode1: + index += kKeySourceSizeMode1 + kKeyIndexSize; + break; + + case kKeyIdMode2: + index += kKeySourceSizeMode2 + kKeyIndexSize; + break; + + case kKeyIdMode3: + index += kKeySourceSizeMode3 + kKeyIndexSize; + break; + } + } + +exit: + return index; +} + +uint8_t Frame::SkipAddrFieldIndex(void) const +{ + uint8_t index = kFcfSize + kDsnSize; // Frame Control field and Sequence Number field + uint16_t fcf; + + VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex); + fcf = GetFrameControlField(); + + // Destination PAN + if (IsDstPanIdPresent(fcf)) + { + index += sizeof(PanId); + } + + // Destination Address switch (fcf & kFcfDstAddrMask) { case kFcfDstAddrNone: break; case kFcfDstAddrShort: - index += sizeof(PanId) + sizeof(ShortAddress); + index += sizeof(ShortAddress); break; case kFcfDstAddrExt: - index += sizeof(PanId) + sizeof(ExtAddress); + index += sizeof(ExtAddress); break; default: ExitNow(index = kInvalidIndex); + break; } // Source PAN @@ -786,35 +861,7 @@ uint8_t Frame::SkipSecurityHeaderIndex(void) const default: ExitNow(index = kInvalidIndex); - } - - VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex); - - // Security Control + Frame Counter + Key Identifier - if ((fcf & kFcfSecurityEnabled) != 0) - { - uint8_t securityControl = *(GetPsdu() + index); - - index += kSecurityControlSize + kFrameCounterSize; - - switch (securityControl & kKeyIdModeMask) - { - case kKeyIdMode0: - index += kKeySourceSizeMode0; - break; - - case kKeyIdMode1: - index += kKeySourceSizeMode1 + kKeyIndexSize; - break; - - case kKeyIdMode2: - index += kKeySourceSizeMode2 + kKeyIndexSize; - break; - - case kKeyIdMode3: - index += kKeySourceSizeMode3 + kKeyIndexSize; - break; - } + break; } exit: diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index a4a4c923b..af9147ccb 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -377,6 +377,14 @@ public: */ uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; } + /** + * This method returns if this IEEE 802.15.4 frame's version is 2015. + * + * @returns TRUE if version is 2015, FALSE otherwise. + * + */ + bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); } + /** * This method indicates whether or not security is enabled. * @@ -445,6 +453,14 @@ public: */ void SetSequence(uint8_t aSequence) { GetPsdu()[kSequenceIndex] = aSequence; } + /** + * This method indicates whether or not the Destination PAN ID is present. + * + * @returns TRUE if the Destination PAN ID is present, FALSE otherwise. + * + */ + bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); } + /** * This method gets the Destination PAN Identifier. * @@ -464,6 +480,14 @@ public: */ void SetDstPanId(PanId aPanId); + /** + * This method indicates whether or not the Destination Address is present for this object. + * + * @retval TRUE if the Destination Address is present, FALSE otherwise. + * + */ + bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); } + /** * This method gets the Destination Address. * @@ -526,6 +550,14 @@ public: */ otError SetSrcPanId(PanId aPanId); + /** + * This method indicates whether or not the Source Address is present for this object. + * + * @retval TRUE if the Source Address is present, FALSE otherwise. + * + */ + bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); } + /** * This method gets the Source Address. * @@ -560,6 +592,25 @@ public: */ void SetSrcAddr(const Address &aAddress); + /** + * This method gets the Security Control Field. + * + * @param[out] aSecurityControlField The Security Control Field. + * + * @retval OT_ERROR_NONE Successfully retrieved the Security Level Identifier. + * @retval OT_ERROR_PARSE Failed to find the security control field in the frame. + * + */ + otError GetSecurityControlField(uint8_t &aSecurityControlField) const; + + /** + * This method sets the Security Control Field. + * + * @param[in] aSecurityControlField The Security Control Field. + * + */ + void SetSecurityControlField(uint8_t aSecurityControlField); + /** * This method gets the Security Level Identifier. * @@ -902,6 +953,7 @@ private: uint8_t FindDstAddrIndex(void) const; uint8_t FindSrcPanIdIndex(void) const; uint8_t FindSrcAddrIndex(void) const; + uint8_t SkipAddrFieldIndex(void) const; uint8_t FindSecurityHeaderIndex(void) const; uint8_t SkipSecurityHeaderIndex(void) const; uint8_t FindPayloadIndex(void) const; @@ -910,6 +962,11 @@ private: #endif static uint8_t GetKeySourceLength(uint8_t aKeyIdMode); + + static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != kFcfDstAddrNone; } + static bool IsDstPanIdPresent(uint16_t aFcf); + static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone; } + static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kFcfFrameVersion2015; } }; /** diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index cabd9cd12..0e3f66bf9 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -405,6 +405,70 @@ void TestMacChannelMask(void) VerifyOrQuit(mask1 != mask2, "ChannelMask.operator== failed"); } +void TestMacFrameApi(void) +{ + uint8_t ack_psdu1[] = {0x02, 0x10, 0x5e, 0xd2, 0x9b}; + + Mac::Frame frame; + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + uint8_t data_psdu1[] = {0x29, 0xee, 0x53, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x01}; + otError error; + uint8_t scf; // SecurityControlField +#endif + + // Imm-Ack, Sequence Number: 94 + // Frame Control Field: 0x1002 + // .... .... .... .010 = Frame Type: Ack (0x2) + // .... .... .... 0... = Security Enabled: False + // .... .... ...0 .... = Frame Pending: False + // .... .... ..0. .... = Acknowledge Request: False + // .... .... .0.. .... = PAN ID Compression: False + // .... ...0 .... .... = Sequence Number Suppression: False + // .... ..0. .... .... = Information Elements Present: False + // .... 00.. .... .... = Destination Addressing Mode: None (0x0) + // ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1) + // 00.. .... .... .... = Source Addressing Mode: None (0x0) + // Sequence Number: 94 + // FCS: 0x9bd2 (Correct) + frame.mPsdu = ack_psdu1; + frame.mLength = sizeof(ack_psdu1); + VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameAck, "Mac::Frame::GetType() failed\n"); + VerifyOrQuit(frame.GetSecurityEnabled() == false, "Mac::Frame::GetSecurityEnabled() failed\n"); + VerifyOrQuit(frame.GetFramePending() == false, "Mac::Frame::GetFramePendIng() failed\n"); + VerifyOrQuit(frame.GetAckRequest() == false, "Mac::Frame::GetAckRequest failed\n"); + VerifyOrQuit(frame.IsIePresent() == false, "Mac::Frame::IsIePresent failed\n"); + VerifyOrQuit(frame.IsDstPanIdPresent() == false, "Mac::Frame::IsDstPanIdPresent failed\n"); + VerifyOrQuit(frame.IsDstAddrPresent() == false, "Mac::Frame::IsDstAddrPresent failed\n"); + VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006, "Mac::Frame::GetVersion failed\n"); + VerifyOrQuit(frame.IsSrcAddrPresent() == false, "Mac::Frame::IsSrcAddrPresent failed\n"); + VerifyOrQuit(frame.GetSequence() == 94, "Mac::Frame::GetSequence failed\n"); + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + // IEEE 802.15.4-2015 Data + // Sequence Number: 83 + // Destination PAN: 0xface + // Destination: 16:6e:0a:00:00:00:00:01 + // Extended Source: 16:6e:0a:00:00:00:00:05 + // Auxiliary Security Header + // Security Control Field: 0x0d + frame.mPsdu = data_psdu1; + frame.mLength = sizeof(data_psdu1); + VerifyOrQuit(frame.IsVersion2015() == true, "Mac::Frame::IsVersion2015 failed\n"); + VerifyOrQuit(frame.IsDstPanIdPresent() == true, "Mac::Frame::IsDstPanIdPresent failed\n"); + VerifyOrQuit(frame.IsDstAddrPresent() == true, "Mac::Frame::IsDstAddrPresent failed\n"); + VerifyOrQuit(frame.IsSrcAddrPresent() == true, "Mac::Frame::IsSrcAddrPresent failed\n"); + VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == OT_ERROR_NONE, + "Mac::Frame::GetSecurityControlField failed\n"); + VerifyOrQuit(scf == 0x0d, "Mac::Frame::GetSecurityControlField value failed\n"); + frame.SetSecurityControlField(0xff); + VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == OT_ERROR_NONE, + "Mac::Frame::GetSecurityControlField failed\n"); + VerifyOrQuit(scf == 0xff, "Mac::Frame::SetSecurityControlField value failed\n"); +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 +} + } // namespace ot int main(void) @@ -413,6 +477,7 @@ int main(void) ot::TestMacNetworkName(); ot::TestMacHeader(); ot::TestMacChannelMask(); + ot::TestMacFrameApi(); printf("All tests passed\n"); return 0; }