diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index b510fb12c..7fda32910 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -1495,5 +1495,181 @@ const char *Ip6::EcnToString(Ecn aEcn) // LCOV_EXCL_STOP +//--------------------------------------------------------------------------------------------------------------------- +// Headers + +Error Headers::ParseFrom(const Message &aMessage) +{ + Error error = kErrorParse; + + Clear(); + + SuccessOrExit(mIp6Header.ParseFrom(aMessage)); + + switch (mIp6Header.GetNextHeader()) + { + case kProtoUdp: + SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mUdp)); + break; + case kProtoTcp: + SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mTcp)); + break; + case kProtoIcmp6: + SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mIcmp)); + break; + default: + break; + } + + error = kErrorNone; + +exit: + return error; +} + +Error Headers::DecompressFrom(const Message & aMessage, + uint16_t aOffset, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest) +{ + static constexpr uint16_t kReadLength = Lowpan::FragmentHeader::kSubsequentFragmentHeaderSize + sizeof(Headers); + + uint8_t frameBuffer[kReadLength]; + uint16_t frameLength; + + frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(frameBuffer)); + + return DecompressFrom(frameBuffer, frameLength, aMacSource, aMacDest, aMessage.GetInstance()); +} + +Error Headers::DecompressFrom(const uint8_t * aFrame, + uint16_t aFrameLength, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest, + Instance & aInstance) +{ + Error error = kErrorNone; + Lowpan::FragmentHeader fragmentHeader; + uint16_t fragmentHeaderLength; + int headerLength; + bool nextHeaderCompressed; + + if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone) + { + // Only the first fragment header is followed by a LOWPAN_IPHC header + VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound); + aFrame += fragmentHeaderLength; + aFrameLength -= fragmentHeaderLength; + } + + VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound); + headerLength = aInstance.Get().DecompressBaseHeader(mIp6Header, nextHeaderCompressed, aMacSource, + aMacDest, aFrame, aFrameLength); + + VerifyOrExit(headerLength > 0, error = kErrorParse); + + aFrame += headerLength; + aFrameLength -= headerLength; + + switch (mIp6Header.GetNextHeader()) + { + case kProtoUdp: + if (nextHeaderCompressed) + { + headerLength = aInstance.Get().DecompressUdpHeader(mHeader.mUdp, aFrame, aFrameLength); + VerifyOrExit(headerLength >= 0, error = kErrorParse); + } + else + { + VerifyOrExit(aFrameLength >= sizeof(Udp::Header), error = kErrorParse); + mHeader.mUdp = *reinterpret_cast(aFrame); + } + break; + + case kProtoTcp: + VerifyOrExit(aFrameLength >= sizeof(Tcp::Header), error = kErrorParse); + mHeader.mTcp = *reinterpret_cast(aFrame); + break; + + case kProtoIcmp6: + VerifyOrExit(aFrameLength >= sizeof(Icmp::Header), error = kErrorParse); + mHeader.mIcmp = *reinterpret_cast(aFrame); + break; + + default: + break; + } + +exit: + return error; +} + +uint16_t Headers::GetSourcePort(void) const +{ + uint16_t port = 0; + + switch (GetIpProto()) + { + case kProtoUdp: + port = mHeader.mUdp.GetSourcePort(); + break; + + case kProtoTcp: + port = mHeader.mTcp.GetSourcePort(); + break; + + default: + break; + } + + return port; +} + +uint16_t Headers::GetDestinationPort(void) const +{ + uint16_t port = 0; + + switch (GetIpProto()) + { + case kProtoUdp: + port = mHeader.mUdp.GetDestinationPort(); + break; + + case kProtoTcp: + port = mHeader.mTcp.GetDestinationPort(); + break; + + default: + break; + } + + return port; +} + +uint16_t Headers::GetChecksum(void) const +{ + uint16_t checksum = 0; + + switch (GetIpProto()) + { + case kProtoUdp: + checksum = mHeader.mUdp.GetChecksum(); + break; + + case kProtoTcp: + checksum = mHeader.mTcp.GetChecksum(); + break; + + case kProtoIcmp6: + checksum = mHeader.mIcmp.GetChecksum(); + break; + + default: + break; + } + + return checksum; +} + } // namespace Ip6 } // namespace ot diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index 0855e1327..3fb9678d9 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -377,6 +377,193 @@ private: #endif }; +/** + * This class represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame. + * + */ +class Headers : private Clearable +{ +public: + /** + * This method parses the IPv6 and UDP/TCP/ICMP6 headers from a given message. + * + * @param[in] aMessage The message to parse the headers from. + * + * @retval kErrorNone The headers are parsed successfully. + * @retval kErrorParse Failed to parse the headers. + * + */ + Error ParseFrom(const Message &aMessage); + + /** + * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. + * + * @param[in] aMessage The message from which to read the lowpan frame. + * @param[in] aOffset The offset in @p aMessage to start reading the frame. + * @param[in] aMacSource The MAC source address. + * @param[in] aMacDest The MAC destination address. + * + * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. + * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. + * @retval kErrorParse Failed to parse the headers. + * + */ + Error DecompressFrom(const Message & aMessage, + uint16_t aOffset, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest); + + /** + * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. + * + * @param[in] aFrame Buffer containig the lowpan frame. + * @param[in] aFrameLength Number of bytes in @p aFrame. + * @param[in] aMacSource The MAC source address. + * @param[in] aMacDest The MAC destination address. + * @param[in] aInstance The OpenThread instance. + * + * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. + * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. + * @retval kErrorParse Failed to parse the headers. + * + */ + Error DecompressFrom(const uint8_t * aFrame, + uint16_t aFrameLength, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest, + Instance & aInstance); + + /** + * This method returns the IPv6 header. + * + * @returns The IPv6 header. + * + */ + const Header &GetIp6Header(void) const { return mIp6Header; } + + /** + * This method returns the IP protocol number from IPv6 Next Header field. + * + * @returns The IP protocol number. + * + */ + uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); } + + /** + * This method returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header. + * + * @returns The ECN value. + * + */ + Ecn GetEcn(void) const { return mIp6Header.GetEcn(); } + + /** + * This method indicates if the protocol number from IPv6 header is UDP. + * + * @retval TRUE If the protocol number in IPv6 header is UDP. + * @retval FALSE If the protocol number in IPv6 header is not UDP. + * + */ + bool IsUdp(void) const { return GetIpProto() == kProtoUdp; } + + /** + * This method indicates if the protocol number from IPv6 header is TCP. + * + * @retval TRUE If the protocol number in IPv6 header is TCP. + * @retval FALSE If the protocol number in IPv6 header is not TCP. + * + */ + bool IsTcp(void) const { return GetIpProto() == kProtoTcp; } + + /** + * This method indicates if the protocol number from IPv6 header is ICMPv6. + * + * @retval TRUE If the protocol number in IPv6 header is ICMPv6. + * @retval FALSE If the protocol number in IPv6 header is not ICMPv6. + * + */ + bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; } + + /** + * This method returns the source IPv6 address from IPv6 header. + * + * @returns The source IPv6 address. + * + */ + const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); } + + /** + * This method returns the destination IPv6 address from IPv6 header. + * + * @returns The destination IPv6 address. + * + */ + const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); } + + /** + * This method returns the UDP header. + * + * This method MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined + * + * @returns The UDP header. + * + */ + const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; } + + /** + * This method returns the TCP header. + * + * This method MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined + * + * @returns The TCP header. + * + */ + const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; } + + /** + * This method returns the ICMPv6 header. + * + * This method MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined + * + * @returns The ICMPv6 header. + * + */ + const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; } + + /** + * This method returns the source port number if header is UDP or TCP, or zero otherwise + * + * @returns The source port number under UDP / TCP or zero. + * + */ + uint16_t GetSourcePort(void) const; + + /** + * This method returns the destination port number if header is UDP or TCP, or zero otherwise. + * + * @returns The destination port number under UDP / TCP or zero. + * + */ + uint16_t GetDestinationPort(void) const; + + /** + * This method returns the checksum values from corresponding UDP, TCP, or ICMPv6 header. + * + * @returns The checksum value. + * + */ + uint16_t GetChecksum(void) const; + +private: + Header mIp6Header; + union + { + Udp::Header mUdp; + Tcp::Header mTcp; + Icmp::Header mIcmp; + } mHeader; +}; + /** * @} * diff --git a/src/core/net/ip6_filter.cpp b/src/core/net/ip6_filter.cpp index 3bfa4f251..0104fac81 100644 --- a/src/core/net/ip6_filter.cpp +++ b/src/core/net/ip6_filter.cpp @@ -52,11 +52,9 @@ RegisterLogModule("Ip6Filter"); bool Filter::Accept(Message &aMessage) const { - bool rval = false; - Header ip6; - Udp::Header udp; - Tcp::Header tcp; - uint16_t dstport; + bool rval = false; + Headers headers; + uint16_t dstPort; // Allow all received IPv6 datagrams with link security enabled if (aMessage.IsLinkSecurityEnabled()) @@ -64,10 +62,11 @@ bool Filter::Accept(Message &aMessage) const ExitNow(rval = true); } - SuccessOrExit(aMessage.Read(0, ip6)); + SuccessOrExit(headers.ParseFrom(aMessage)); // Allow only link-local unicast or multicast - VerifyOrExit(ip6.GetDestination().IsLinkLocal() || ip6.GetDestination().IsLinkLocalMulticast()); + VerifyOrExit(headers.GetDestinationAddress().IsLinkLocal() || + headers.GetDestinationAddress().IsLinkLocalMulticast()); // Allow all link-local IPv6 datagrams when Thread is not enabled if (Get().GetRole() == Mle::kRoleDisabled) @@ -75,14 +74,13 @@ bool Filter::Accept(Message &aMessage) const ExitNow(rval = true); } - switch (ip6.GetNextHeader()) + dstPort = headers.GetDestinationPort(); + + switch (headers.GetIpProto()) { case kProtoUdp: - SuccessOrExit(aMessage.Read(sizeof(ip6), udp)); - dstport = udp.GetDestinationPort(); - // Allow MLE traffic - if (dstport == Mle::kUdpPort) + if (dstPort == Mle::kUdpPort) { ExitNow(rval = true); } @@ -90,7 +88,7 @@ bool Filter::Accept(Message &aMessage) const #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE // Allow native commissioner traffic if (Get().GetSecurityPolicy().mNativeCommissioningEnabled && - dstport == Get().GetUdpPort()) + dstPort == Get().GetUdpPort()) { ExitNow(rval = true); } @@ -98,8 +96,6 @@ bool Filter::Accept(Message &aMessage) const break; case kProtoTcp: - SuccessOrExit(aMessage.Read(sizeof(ip6), tcp)); - dstport = tcp.GetDestinationPort(); break; default: @@ -108,7 +104,7 @@ bool Filter::Accept(Message &aMessage) const } // Check against allowed unsecure port list - rval = mUnsecurePorts.Contains(dstport); + rval = mUnsecurePorts.Contains(dstPort); exit: return rval; diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 7a1a18e8a..f6e07c84d 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -469,39 +469,6 @@ void MeshForwarder::GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac:: } } -Error MeshForwarder::DecompressIp6Header(const uint8_t * aFrame, - uint16_t aFrameLength, - const Mac::Address &aMacSource, - const Mac::Address &aMacDest, - Ip6::Header & aIp6Header, - uint8_t & aHeaderLength, - bool & aNextHeaderCompressed) -{ - Error error = kErrorNone; - const uint8_t * start = aFrame; - Lowpan::FragmentHeader fragmentHeader; - uint16_t fragmentHeaderLength; - int headerLength; - - if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone) - { - // Only the first fragment header is followed by a LOWPAN_IPHC header - VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound); - aFrame += fragmentHeaderLength; - aFrameLength -= fragmentHeaderLength; - } - - VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound); - headerLength = Get().DecompressBaseHeader(aIp6Header, aNextHeaderCompressed, aMacSource, aMacDest, - aFrame, aFrameLength); - - VerifyOrExit(headerLength > 0, error = kErrorParse); - aHeaderLength = static_cast(aFrame - start) + static_cast(headerLength); - -exit: - return error; -} - Mac::TxFrame *MeshForwarder::HandleFrameRequest(Mac::TxFrames &aTxFrames) { Mac::TxFrame *frame = nullptr; @@ -1525,59 +1492,27 @@ Error MeshForwarder::GetFramePriority(const uint8_t * aFrame, const Mac::Address &aMacDest, Message::Priority & aPriority) { - Error error = kErrorNone; - Ip6::Header ip6Header; - uint16_t dstPort; - uint8_t headerLength; - bool nextHeaderCompressed; + Error error = kErrorNone; + Ip6::Headers headers; - SuccessOrExit(error = DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, ip6Header, headerLength, - nextHeaderCompressed)); - aPriority = Ip6::Ip6::DscpToPriority(ip6Header.GetDscp()); + SuccessOrExit(error = headers.DecompressFrom(aFrame, aFrameLength, aMacSource, aMacDest, GetInstance())); - aFrame += headerLength; - aFrameLength -= headerLength; + aPriority = Ip6::Ip6::DscpToPriority(headers.GetIp6Header().GetDscp()); - switch (ip6Header.GetNextHeader()) + // Only ICMPv6 error messages are prioritized. + if (headers.IsIcmp6() && headers.GetIcmpHeader().IsError()) { - case Ip6::kProtoIcmp6: + aPriority = Message::kPriorityNet; + } - VerifyOrExit(aFrameLength >= sizeof(Ip6::Icmp::Header), error = kErrorParse); + if (headers.IsUdp()) + { + uint16_t destPort = headers.GetUdpHeader().GetDestinationPort(); - // Only ICMPv6 error messages are prioritized. - if (reinterpret_cast(aFrame)->IsError()) + if ((destPort == Mle::kUdpPort) || (destPort == Tmf::kUdpPort)) { aPriority = Message::kPriorityNet; } - - break; - - case Ip6::kProtoUdp: - - if (nextHeaderCompressed) - { - Ip6::Udp::Header udpHeader; - - VerifyOrExit(Get().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0, - error = kErrorParse); - - dstPort = udpHeader.GetDestinationPort(); - } - else - { - VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = kErrorParse); - dstPort = reinterpret_cast(aFrame)->GetDestinationPort(); - } - - if ((dstPort == Mle::kUdpPort) || (dstPort == Tmf::kUdpPort)) - { - aPriority = Message::kPriorityNet; - } - - break; - - default: - break; } exit: @@ -1688,52 +1623,6 @@ uint16_t MeshForwarder::CalcFrameVersion(const Neighbor *aNeighbor, bool aIePres // LCOV_EXCL_START -Error MeshForwarder::ParseIp6UdpTcpHeader(const Message &aMessage, - Ip6::Header & aIp6Header, - uint16_t & aChecksum, - uint16_t & aSourcePort, - uint16_t & aDestPort) -{ - Error error = kErrorParse; - union - { - Ip6::Udp::Header udp; - Ip6::Tcp::Header tcp; - } header; - - aChecksum = 0; - aSourcePort = 0; - aDestPort = 0; - - SuccessOrExit(aMessage.Read(0, aIp6Header)); - VerifyOrExit(aIp6Header.IsVersion6()); - - switch (aIp6Header.GetNextHeader()) - { - case Ip6::kProtoUdp: - SuccessOrExit(aMessage.Read(sizeof(Ip6::Header), header.udp)); - aChecksum = header.udp.GetChecksum(); - aSourcePort = header.udp.GetSourcePort(); - aDestPort = header.udp.GetDestinationPort(); - break; - - case Ip6::kProtoTcp: - SuccessOrExit(aMessage.Read(sizeof(Ip6::Header), header.tcp)); - aChecksum = header.tcp.GetChecksum(); - aSourcePort = header.tcp.GetSourcePort(); - aDestPort = header.tcp.GetDestinationPort(); - break; - - default: - break; - } - - error = kErrorNone; - -exit: - return error; -} - #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aError) @@ -1770,31 +1659,31 @@ const char *MeshForwarder::MessagePriorityToString(const Message &aMessage) } #if OPENTHREAD_CONFIG_LOG_SRC_DST_IP_ADDRESSES -void MeshForwarder::LogIp6SourceDestAddresses(Ip6::Header &aIp6Header, - uint16_t aSourcePort, - uint16_t aDestPort, - LogLevel aLogLevel) +void MeshForwarder::LogIp6SourceDestAddresses(const Ip6::Headers &aHeaders, LogLevel aLogLevel) { - if (aSourcePort != 0) + uint16_t srcPort = aHeaders.GetSourcePort(); + uint16_t dstPort = aHeaders.GetDestinationPort(); + + if (srcPort != 0) { - LogAt(aLogLevel, " src:[%s]:%d", aIp6Header.GetSource().ToString().AsCString(), aSourcePort); + LogAt(aLogLevel, " src:[%s]:%d", aHeaders.GetSourceAddress().ToString().AsCString(), srcPort); } else { - LogAt(aLogLevel, " src:[%s]", aIp6Header.GetSource().ToString().AsCString()); + LogAt(aLogLevel, " src:[%s]", aHeaders.GetSourceAddress().ToString().AsCString()); } - if (aDestPort != 0) + if (dstPort != 0) { - LogAt(aLogLevel, " dst:[%s]:%d", aIp6Header.GetDestination().ToString().AsCString(), aDestPort); + LogAt(aLogLevel, " dst:[%s]:%d", aHeaders.GetDestinationAddress().ToString().AsCString(), dstPort); } else { - LogAt(aLogLevel, " dst:[%s]", aIp6Header.GetDestination().ToString().AsCString()); + LogAt(aLogLevel, " dst:[%s]", aHeaders.GetDestinationAddress().ToString().AsCString()); } } #else -void MeshForwarder::LogIp6SourceDestAddresses(Ip6::Header &, uint16_t, uint16_t, LogLevel) +void MeshForwarder::LogIp6SourceDestAddresses(const Ip6::Headers &, LogLevel) { } #endif @@ -1805,15 +1694,12 @@ void MeshForwarder::LogIp6Message(MessageAction aAction, Error aError, LogLevel aLogLevel) { - Ip6::Header ip6Header; - uint16_t checksum; - uint16_t sourcePort; - uint16_t destPort; - bool shouldLogRss; - bool shouldLogRadio = false; - const char *radioString = ""; + Ip6::Headers headers; + bool shouldLogRss; + bool shouldLogRadio = false; + const char * radioString = ""; - SuccessOrExit(ParseIp6UdpTcpHeader(aMessage, ip6Header, checksum, sourcePort, destPort)); + SuccessOrExit(headers.ParseFrom(aMessage)); shouldLogRss = (aAction == kMessageReceive) || (aAction == kMessageReassemblyDrop); @@ -1823,8 +1709,8 @@ void MeshForwarder::LogIp6Message(MessageAction aAction, #endif LogAt(aLogLevel, "%s IPv6 %s msg, len:%d, chksum:%04x, ecn:%s%s%s, sec:%s%s%s, prio:%s%s%s%s%s", - MessageActionToString(aAction, aError), Ip6::Ip6::IpProtoToString(ip6Header.GetNextHeader()), - aMessage.GetLength(), checksum, Ip6::Ip6::EcnToString(ip6Header.GetEcn()), + MessageActionToString(aAction, aError), Ip6::Ip6::IpProtoToString(headers.GetIpProto()), aMessage.GetLength(), + headers.GetChecksum(), Ip6::Ip6::EcnToString(headers.GetEcn()), (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"), (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(), ToYesNo(aMessage.IsLinkSecurityEnabled()), @@ -1835,7 +1721,7 @@ void MeshForwarder::LogIp6Message(MessageAction aAction, if (aAction != kMessagePrepareIndirect) { - LogIp6SourceDestAddresses(ip6Header, sourcePort, destPort, aLogLevel); + LogIp6SourceDestAddresses(headers, aLogLevel); } exit: diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 603e567ef..88e4fa5de 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -170,7 +170,6 @@ class MeshForwarder : public InstanceLocator, private NonCopyable friend class Ip6::Ip6; friend class Mle::DiscoverScanner; friend class TimeTicker; - friend class Utils::HistoryTracker; public: /** @@ -390,36 +389,23 @@ private: }; #endif // OPENTHREAD_FTD - void SendIcmpErrorIfDstUnreach(const Message & aMessage, - const Mac::Address &aMacSource, - const Mac::Address &aMacDest); - Error CheckReachability(const uint8_t * aFrame, - uint16_t aFrameLength, - const Mac::Address &aMeshSource, - const Mac::Address &aMeshDest); - void UpdateRoutes(const uint8_t * aFrame, - uint16_t aFrameLength, - const Mac::Address &aMeshSource, - const Mac::Address &aMeshDest); - - Error DecompressIp6Header(const uint8_t * aFrame, - uint16_t aFrameLength, - const Mac::Address &aMacSource, - const Mac::Address &aMacDest, - Ip6::Header & aIp6Header, - uint8_t & aHeaderLength, - bool & aNextHeaderCompressed); + void SendIcmpErrorIfDstUnreach(const Message & aMessage, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest); + Error CheckReachability(const uint8_t * aFrame, + uint16_t aFrameLength, + const Mac::Address &aMeshSource, + const Mac::Address &aMeshDest); + void UpdateRoutes(const uint8_t * aFrame, + uint16_t aFrameLength, + const Mac::Address &aMeshSource, + const Mac::Address &aMeshDest); Error FrameToMessage(const uint8_t * aFrame, uint16_t aFrameLength, uint16_t aDatagramSize, const Mac::Address &aMacSource, const Mac::Address &aMacDest, Message *& aMessage); - Error GetIp6Header(const uint8_t * aFrame, - uint16_t aFrameLength, - const Mac::Address &aMacSource, - const Mac::Address &aMacDest, - Ip6::Header & aIp6Header); void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); Message *PrepareNextDirectTransmission(void); @@ -527,25 +513,11 @@ private: const Mac::Address &aMacDest, bool aIsSecure); - static Error ParseIp6UdpTcpHeader(const Message &aMessage, - Ip6::Header & aIp6Header, - uint16_t & aChecksum, - uint16_t & aSourcePort, - uint16_t & aDestPort); - #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) const char *MessageActionToString(MessageAction aAction, Error aError); const char *MessagePriorityToString(const Message &aMessage); #if OPENTHREAD_FTD - Error DecompressIp6UdpTcpHeader(const Message & aMessage, - uint16_t aOffset, - const Mac::Address &aMeshSource, - const Mac::Address &aMeshDest, - Ip6::Header & aIp6Header, - uint16_t & aChecksum, - uint16_t & aSourcePort, - uint16_t & aDestPort); Error LogMeshFragmentHeader(MessageAction aAction, const Message & aMessage, const Mac::Address *aMacAddress, @@ -565,10 +537,7 @@ private: Error aError, LogLevel aLogLevel); #endif - void LogIp6SourceDestAddresses(Ip6::Header &aIp6Header, - uint16_t aSourcePort, - uint16_t aDestPort, - LogLevel aLogLevel); + void LogIp6SourceDestAddresses(const Ip6::Headers &aHeaders, LogLevel aLogLevel); void LogIp6Message(MessageAction aAction, const Message & aMessage, const Mac::Address *aAddress, diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index ef1f60df1..d7c43aef0 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -632,19 +632,6 @@ exit: return error; } -Error MeshForwarder::GetIp6Header(const uint8_t * aFrame, - uint16_t aFrameLength, - const Mac::Address &aMacSource, - const Mac::Address &aMacDest, - Ip6::Header & aIp6Header) -{ - uint8_t headerLength; - bool nextHeaderCompressed; - - return DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, aIp6Header, headerLength, - nextHeaderCompressed); -} - void MeshForwarder::SendIcmpErrorIfDstUnreach(const Message & aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest) @@ -826,23 +813,25 @@ void MeshForwarder::UpdateRoutes(const uint8_t * aFrame, const Mac::Address &aMeshSource, const Mac::Address &aMeshDest) { - Ip6::Header ip6Header; - Neighbor * neighbor; + Ip6::Headers ip6Headers; + Neighbor * neighbor; VerifyOrExit(!aMeshDest.IsBroadcast() && aMeshSource.IsShort()); - SuccessOrExit(GetIp6Header(aFrame, aFrameLength, aMeshSource, aMeshDest, ip6Header)); - if (!ip6Header.GetSource().GetIid().IsLocator() && - Get().IsOnMesh(ip6Header.GetSource()) /* only for on mesh address which may require AQ */) + SuccessOrExit(ip6Headers.DecompressFrom(aFrame, aFrameLength, aMeshSource, aMeshDest, GetInstance())); + + if (!ip6Headers.GetSourceAddress().GetIid().IsLocator() && + Get().IsOnMesh(ip6Headers.GetSourceAddress())) { // FTDs MAY add/update EID-to-RLOC Map Cache entries by - // inspecting packets being received. + // inspecting packets being received only for on mesh + // addresses. - Get().UpdateSnoopedCacheEntry(ip6Header.GetSource(), aMeshSource.GetShort(), + Get().UpdateSnoopedCacheEntry(ip6Headers.GetSourceAddress(), aMeshSource.GetShort(), aMeshDest.GetShort()); } - neighbor = Get().FindNeighbor(ip6Header.GetSource()); + neighbor = Get().FindNeighbor(ip6Headers.GetSourceAddress()); VerifyOrExit(neighbor != nullptr && !neighbor->IsFullThreadDevice()); if (!Mle::Mle::RouterIdMatch(aMeshSource.GetShort(), Get().GetShortAddress())) @@ -1067,97 +1056,20 @@ exit: return error; } -Error MeshForwarder::DecompressIp6UdpTcpHeader(const Message & aMessage, - uint16_t aOffset, - const Mac::Address &aMeshSource, - const Mac::Address &aMeshDest, - Ip6::Header & aIp6Header, - uint16_t & aChecksum, - uint16_t & aSourcePort, - uint16_t & aDestPort) -{ - Error error = kErrorParse; - int headerLength; - bool nextHeaderCompressed; - uint8_t frameBuffer[sizeof(Ip6::Header)]; - uint16_t frameLength; - union - { - Ip6::Udp::Header udp; - Ip6::Tcp::Header tcp; - } header; - - aChecksum = 0; - aSourcePort = 0; - aDestPort = 0; - - // Read and decompress the IPv6 header - - frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(frameBuffer)); - - headerLength = Get().DecompressBaseHeader(aIp6Header, nextHeaderCompressed, aMeshSource, aMeshDest, - frameBuffer, frameLength); - VerifyOrExit(headerLength >= 0); - - aOffset += headerLength; - - // Read and decompress UDP or TCP header - - switch (aIp6Header.GetNextHeader()) - { - case Ip6::kProtoUdp: - if (nextHeaderCompressed) - { - frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(Ip6::Udp::Header)); - headerLength = Get().DecompressUdpHeader(header.udp, frameBuffer, frameLength); - VerifyOrExit(headerLength >= 0); - } - else - { - SuccessOrExit(aMessage.Read(aOffset, header.udp)); - } - - aChecksum = header.udp.GetChecksum(); - aSourcePort = header.udp.GetSourcePort(); - aDestPort = header.udp.GetDestinationPort(); - break; - - case Ip6::kProtoTcp: - SuccessOrExit(aMessage.Read(aOffset, header.tcp)); - aChecksum = header.tcp.GetChecksum(); - aSourcePort = header.tcp.GetSourcePort(); - aDestPort = header.tcp.GetDestinationPort(); - break; - - default: - break; - } - - error = kErrorNone; - -exit: - return error; -} - void MeshForwarder::LogMeshIpHeader(const Message & aMessage, uint16_t aOffset, const Mac::Address &aMeshSource, const Mac::Address &aMeshDest, LogLevel aLogLevel) { - uint16_t checksum; - uint16_t sourcePort; - uint16_t destPort; - Ip6::Header ip6Header; + Ip6::Headers headers; - SuccessOrExit(DecompressIp6UdpTcpHeader(aMessage, aOffset, aMeshSource, aMeshDest, ip6Header, checksum, sourcePort, - destPort)); + SuccessOrExit(headers.DecompressFrom(aMessage, aOffset, aMeshSource, aMeshDest)); - LogAt(aLogLevel, " IPv6 %s msg, chksum:%04x, ecn:%s, prio:%s", - Ip6::Ip6::IpProtoToString(ip6Header.GetNextHeader()), checksum, Ip6::Ip6::EcnToString(ip6Header.GetEcn()), - MessagePriorityToString(aMessage)); + LogAt(aLogLevel, " IPv6 %s msg, chksum:%04x, ecn:%s, prio:%s", Ip6::Ip6::IpProtoToString(headers.GetIpProto()), + headers.GetChecksum(), Ip6::Ip6::EcnToString(headers.GetEcn()), MessagePriorityToString(aMessage)); - LogIp6SourceDestAddresses(ip6Header, sourcePort, destPort, aLogLevel); + LogIp6SourceDestAddresses(headers, aLogLevel); exit: return; diff --git a/src/core/utils/history_tracker.cpp b/src/core/utils/history_tracker.cpp index fd4b9d48d..199146569 100644 --- a/src/core/utils/history_tracker.cpp +++ b/src/core/utils/history_tracker.cpp @@ -42,6 +42,7 @@ #include "common/locator_getters.hpp" #include "common/string.hpp" #include "common/timer.hpp" +#include "net/ip6_headers.hpp" namespace ot { namespace Utils { @@ -78,33 +79,26 @@ exit: void HistoryTracker::RecordMessage(const Message &aMessage, const Mac::Address &aMacAddresss, MessageType aType) { - MessageInfo * entry = nullptr; - Ip6::Header ip6Header; - Ip6::Icmp::Header icmp6Header; - uint8_t ip6Proto; - uint16_t checksum; - uint16_t sourcePort; - uint16_t destPort; + MessageInfo *entry = nullptr; + Ip6::Headers headers; VerifyOrExit(aMessage.GetType() == Message::kTypeIp6); - SuccessOrExit(MeshForwarder::ParseIp6UdpTcpHeader(aMessage, ip6Header, checksum, sourcePort, destPort)); - - ip6Proto = ip6Header.GetNextHeader(); + SuccessOrExit(headers.ParseFrom(aMessage)); #if OPENTHREAD_CONFIG_HISTORY_TRACKER_EXCLUDE_THREAD_CONTROL_MESSAGES - if (ip6Proto == Ip6::kProtoUdp) + if (headers.IsUdp()) { uint16_t port = 0; switch (aType) { case kRxMessage: - port = destPort; + port = headers.GetDestinationPort(); break; case kTxMessage: - port = sourcePort; + port = headers.GetSourcePort(); break; } @@ -112,16 +106,6 @@ void HistoryTracker::RecordMessage(const Message &aMessage, const Mac::Address & } #endif - if (ip6Proto == Ip6::kProtoIcmp6) - { - SuccessOrExit(aMessage.Read(sizeof(Ip6::Header), icmp6Header)); - checksum = icmp6Header.GetChecksum(); - } - else - { - icmp6Header.Clear(); - } - switch (aType) { case kRxMessage: @@ -135,15 +119,15 @@ void HistoryTracker::RecordMessage(const Message &aMessage, const Mac::Address & VerifyOrExit(entry != nullptr); - entry->mPayloadLength = ip6Header.GetPayloadLength(); + entry->mPayloadLength = headers.GetIp6Header().GetPayloadLength(); entry->mNeighborRloc16 = aMacAddresss.IsShort() ? aMacAddresss.GetShort() : kInvalidRloc16; - entry->mSource.mAddress = ip6Header.GetSource(); - entry->mSource.mPort = sourcePort; - entry->mDestination.mAddress = ip6Header.GetDestination(); - entry->mDestination.mPort = destPort; - entry->mChecksum = checksum; - entry->mIpProto = ip6Proto; - entry->mIcmp6Type = icmp6Header.GetType(); + entry->mSource.mAddress = headers.GetSourceAddress(); + entry->mSource.mPort = headers.GetSourcePort(); + entry->mDestination.mAddress = headers.GetDestinationAddress(); + entry->mDestination.mPort = headers.GetDestinationPort(); + entry->mChecksum = headers.GetChecksum(); + entry->mIpProto = headers.GetIpProto(); + entry->mIcmp6Type = headers.IsIcmp6() ? headers.GetIcmpHeader().GetType() : 0; entry->mAveRxRss = (aType == kRxMessage) ? aMessage.GetRssAverager().GetAverage() : kInvalidRss; entry->mLinkSecurity = aMessage.IsLinkSecurityEnabled(); entry->mTxSuccess = (aType == kTxMessage) ? aMessage.GetTxSuccess() : true;