From f2b351e4f96a07006f5bd2fcb8f9317a8d7ce946 Mon Sep 17 00:00:00 2001 From: kangping Date: Thu, 25 Mar 2021 23:33:34 +0800 Subject: [PATCH] [border-router] enhance on-link prefix check (#6327) This commit applies on-link validations described by https://www.ietf.org/archive/id/draft-lemon-stub-networks-02.html#section-3.1.1 --- .../border_router/router_advertisement.hpp | 28 ++++++++++++++++++- src/core/border_router/routing_manager.cpp | 26 +++++++++++------ src/core/border_router/routing_manager.hpp | 3 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/core/border_router/router_advertisement.hpp b/src/core/border_router/router_advertisement.hpp index e34641271..b8bf203e9 100644 --- a/src/core/border_router/router_advertisement.hpp +++ b/src/core/border_router/router_advertisement.hpp @@ -182,6 +182,14 @@ public: */ PrefixInfoOption(void); + /** + * This method returns the on-link flag. + * + * @returns A boolean which indicates whether the on-link flag is set. + * + */ + bool GetOnLink(void) const { return (mReserved1 & kOnLinkFlagMask) != 0; } + /** * This method sets the on-link (L) flag. * @@ -190,6 +198,14 @@ public: */ void SetOnLink(bool aOnLink); + /** + * This method returns the autonomous address-configuration (A) flag. + * + * @returns A boolean which indicates whether the A flag is set. + * + */ + bool GetAutoAddrConfig(void) const { return (mReserved1 & kAutoConfigFlagMask) != 0; } + /** * This method sets the autonomous address-configuration (A) flag. * @@ -393,10 +409,20 @@ public: mHeader.mData.m16[kRouteLifetimeIdx] = HostSwap16(aRouterLifetime); } + /** + * This method returns the Managed Address Configuration ('m') flag. + * + * @returns A boolean which indicates whether the 'm' flag is set. + * + */ + bool GetManagedAddrConfig(void) const { return (mHeader.mData.m8[kReservedIdx] & kManagedAddressConfigMask) != 0; } + private: enum : uint8_t { - kRouteLifetimeIdx = 1u, // The index of Route Lifetime in ICMPv6 Header Data. in unit of 2 octets. + kRouteLifetimeIdx = 1u, // The index of Route Lifetime in ICMPv6 Header Data. In unit of 2 octets. + kReservedIdx = 1u, // The idex of Reserved byte in ICMPv6 Header Data. In unit of 1 octet. + kManagedAddressConfigMask = 0x80u, // The bitmask of the Managed Address Configuration ('m') flag. }; Ip6::Icmp::Header mHeader; // The common ICMPv6 header. diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 54459e9e9..adb2dc9ee 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -799,6 +799,12 @@ bool RoutingManager::IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix) (aOmrPrefix.mLength >= 3 && (aOmrPrefix.GetBytes()[0] & 0xE0) == 0x20); } +bool RoutingManager::IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig) +{ + return IsValidOnLinkPrefix(aPio.GetPrefix()) && aPio.GetOnLink() && + (aPio.GetAutoAddrConfig() || aManagedAddrConfig); +} + bool RoutingManager::IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix) { // Accept ULA prefix with length of 64 bits and GUA prefix. @@ -924,18 +930,20 @@ void RoutingManager::HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, using RouterAdv::RouteInfoOption; using RouterAdv::RouterAdvMessage; - bool needReevaluate = false; - const uint8_t *optionsBegin; - uint16_t optionsLength; - const Option * option; + bool needReevaluate = false; + const uint8_t * optionsBegin; + uint16_t optionsLength; + const Option * option; + const RouterAdvMessage *routerAdvMessage; VerifyOrExit(aBufferLength >= sizeof(RouterAdvMessage)); otLogInfoBr("received Router Advertisement from %s on interface %u", aSrcAddress.ToString().AsCString(), mInfraIfIndex); - optionsBegin = aBuffer + sizeof(RouterAdvMessage); - optionsLength = aBufferLength - sizeof(RouterAdvMessage); + routerAdvMessage = reinterpret_cast(aBuffer); + optionsBegin = aBuffer + sizeof(RouterAdvMessage); + optionsLength = aBufferLength - sizeof(RouterAdvMessage); option = nullptr; while ((option = Option::GetNextOption(option, optionsBegin, optionsLength)) != nullptr) @@ -948,7 +956,7 @@ void RoutingManager::HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, if (pio->IsValid()) { - needReevaluate |= UpdateDiscoveredPrefixes(*pio); + needReevaluate |= UpdateDiscoveredPrefixes(*pio, routerAdvMessage->GetManagedAddrConfig()); } } break; @@ -978,12 +986,12 @@ exit: return; } -bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio) +bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig) { Ip6::Prefix prefix = aPio.GetPrefix(); bool needReevaluate = false; - if (!IsValidOnLinkPrefix(prefix)) + if (!IsValidOnLinkPrefix(aPio, aManagedAddrConfig)) { otLogInfoBr("ignore invalid prefix in PIO: %s", prefix.ToString().AsCString()); ExitNow(); diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index c4a9e8171..f7b20174b 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -230,7 +230,7 @@ private: void HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); void HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); - bool UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio); + bool UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig); bool UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption &aRio); bool InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix = nullptr, bool aIsOnLinkPrefix = true); void InvalidateAllDiscoveredPrefixes(void); @@ -242,6 +242,7 @@ private: static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix); + static bool IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig); static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); static bool ContainsPrefix(const Ip6::Prefix &aPrefix, const Ip6::Prefix *aPrefixList, uint8_t aPrefixNum); static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime);