| /* |
| * Copyright (c) 2020, The OpenThread Authors. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @file |
| * This file includes definitions for IPv6 Neighbor Discovery (ND). |
| * |
| * See RFC 4861 (https://tools.ietf.org/html/rfc4861) and RFC 4191 (https://tools.ietf.org/html/rfc4191). |
| */ |
| |
| #ifndef OT_CORE_NET_ND6_HPP_ |
| #define OT_CORE_NET_ND6_HPP_ |
| |
| #include "openthread-core-config.h" |
| |
| #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE |
| |
| #include <stdint.h> |
| |
| #include <openthread/netdata.h> |
| #include <openthread/platform/infra_if.h> |
| #include <openthread/platform/toolchain.h> |
| |
| #include "border_router/infra_if.hpp" |
| #include "common/const_cast.hpp" |
| #include "common/encoding.hpp" |
| #include "common/equatable.hpp" |
| #include "common/heap_array.hpp" |
| #include "net/icmp6.hpp" |
| #include "net/ip6.hpp" |
| #include "net/ip6_headers.hpp" |
| #include "thread/network_data_types.hpp" |
| |
| namespace ot { |
| namespace Ip6 { |
| namespace Nd { |
| |
| typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference |
| typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer for an ICMPv6 packet. |
| typedef otPlatInfraIfLinkLayerAddress LinkLayerAddress; ///< An infra-if link-layer address. |
| |
| /** |
| * Represents the variable length options in Neighbor Discovery messages. |
| * |
| * @sa PrefixInfoOption |
| * @sa RouteInfoOption |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class Option |
| { |
| friend class RouterAdvert; |
| |
| public: |
| enum Type : uint8_t |
| { |
| kSourceLinkLayerAddr = 1, ///< Source Link Layer Address Option. |
| kTargetLinkLayerAddr = 2, ///< Target Link Layer Address Option. |
| kTypePrefixInfo = 3, ///< Prefix Information Option. |
| kTypeRouteInfo = 24, ///< Route Information Option. |
| kTypeRecursiveDnsServer = 25, ///< Recursive DNS Server (RDNSS) Option. |
| kTypeRaFlagsExtension = 26, ///< RA Flags Extension Option. |
| kTypeNat64Prefix = 38, ///< NAT64 Prefix Option (aka PREF64 Option). |
| }; |
| |
| static constexpr uint16_t kLengthUnit = 8; ///< The unit of length in octets. |
| |
| /** |
| * Gets the option type. |
| * |
| * @returns The option type. |
| */ |
| uint8_t GetType(void) const { return mType; } |
| |
| /** |
| * Sets the option type. |
| * |
| * @param[in] aType The option type. |
| */ |
| void SetType(Type aType) { mType = aType; } |
| |
| /** |
| * Sets the length based on a given total option size in bytes. |
| * |
| * Th option must end on a 64-bit boundary, so the length is derived as `(aSize + 7) / 8 * 8`. |
| * |
| * @param[in] aSize The size of option in bytes. |
| */ |
| void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>(DivideAndRoundUp(aSize, kLengthUnit)); } |
| |
| /** |
| * Returns the size of the option in bytes. |
| * |
| * @returns The size of the option in bytes. |
| */ |
| uint16_t GetSize(void) const { return mLength * kLengthUnit; } |
| |
| /** |
| * Sets the length of the option (in unit of 8 bytes). |
| * |
| * @param[in] aLength The length of the option in unit of 8 bytes. |
| */ |
| void SetLength(uint8_t aLength) { mLength = aLength; } |
| |
| /** |
| * Returns the length of the option (in unit of 8 bytes). |
| * |
| * @returns The length of the option in unit of 8 bytes. |
| */ |
| uint16_t GetLength(void) const { return mLength; } |
| |
| /** |
| * Indicates whether or not this option is valid. |
| * |
| * @retval TRUE The option is valid. |
| * @retval FALSE The option is not valid. |
| */ |
| bool IsValid(void) const { return mLength > 0; } |
| |
| private: |
| class Iterator : public Unequatable<Iterator> |
| { |
| public: |
| Iterator(void); |
| Iterator(const void *aStart, const void *aEnd); |
| |
| const Option &operator*(void) { return *mOption; } |
| void operator++(void) { Advance(); } |
| void operator++(int) { Advance(); } |
| bool operator==(const Iterator &aOther) const { return mOption == aOther.mOption; } |
| |
| private: |
| static const Option *Next(const Option *aOption); |
| void Advance(void); |
| const Option *Validate(const Option *aOption) const; |
| |
| const Option *mOption; |
| const Option *mEnd; |
| }; |
| |
| uint8_t mType; // Type of the option. |
| uint8_t mLength; // Length of the option in unit of 8 octets, including the `mType` and `mLength` fields. |
| } OT_TOOL_PACKED_END; |
| |
| /** |
| * Represents the Prefix Information Option. |
| * |
| * See section 4.6.2 of RFC 4861 for definition of this option [https://tools.ietf.org/html/rfc4861#section-4.6.2] |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class PrefixInfoOption : public Option, private Clearable<PrefixInfoOption> |
| { |
| friend class Clearable<PrefixInfoOption>; |
| |
| public: |
| static constexpr Type kType = kTypePrefixInfo; ///< Prefix Information Option Type. |
| |
| static constexpr uint8_t kOnLinkFlag = 0x80; ///< On-link - L flag. |
| static constexpr uint8_t kAutoConfigFlag = 0x40; ///< Autonomous address-configuration - A flag. |
| static constexpr uint8_t kDhcp6PdPreferredFlag = 0x10; ///< DHCPv6-PD preferred - P flag. |
| |
| typedef uint8_t Flags; ///< Represents the flags as a bitmap. |
| |
| /** |
| * Initializes the Prefix Info option with proper type and length and sets all other fields to zero. |
| */ |
| void Init(void); |
| |
| /** |
| * Gets the raw flag bitmap. |
| * |
| * @return The flags bitmap. |
| */ |
| Flags GetFlags(void) const { return mFlags; } |
| |
| /** |
| * Sets the raw flag bitmap. |
| * |
| * @param[in] aFlags The flags bitmap. |
| */ |
| void SetFlags(Flags aFlags) { mFlags = aFlags; } |
| |
| /** |
| * Indicates whether or not the on-link flag is set. |
| * |
| * @retval TRUE The on-link flag is set. |
| * @retval FALSE The on-link flag is not set. |
| */ |
| bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlag) != 0; } |
| |
| /** |
| * Sets the on-link (L) flag. |
| */ |
| void SetOnLinkFlag(void) { mFlags |= kOnLinkFlag; } |
| |
| /** |
| * Clears the on-link (L) flag. |
| */ |
| void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlag; } |
| |
| /** |
| * Indicates whether or not the autonomous address-configuration (A) flag is set. |
| * |
| * @retval TRUE The auto address-config flag is set. |
| * @retval FALSE The auto address-config flag is not set. |
| */ |
| bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlag) != 0; } |
| |
| /** |
| * Sets the autonomous address-configuration (A) flag. |
| */ |
| void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlag; } |
| |
| /** |
| * Clears the autonomous address-configuration (A) flag. |
| */ |
| void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlag; } |
| |
| /** |
| * Indicates whether or not the DhCPv6-PD Preferred (P) flag is set. |
| * |
| * @retval TRUE The DHCPv6-PD Preferred (P) flag is set. |
| * @retval FALSE The DHCPv6-PD Preferred (P) flag is not set. |
| */ |
| bool IsDhcp6PdPreferredFlagSet(void) const { return (mFlags & kDhcp6PdPreferredFlag) != 0; } |
| |
| /** |
| * Sets the valid lifetime of the prefix in seconds. |
| * |
| * @param[in] aValidLifetime The valid lifetime in seconds. |
| */ |
| void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = BigEndian::HostSwap32(aValidLifetime); } |
| |
| /** |
| * THis method gets the valid lifetime of the prefix in seconds. |
| * |
| * @returns The valid lifetime in seconds. |
| */ |
| uint32_t GetValidLifetime(void) const { return BigEndian::HostSwap32(mValidLifetime); } |
| |
| /** |
| * Sets the preferred lifetime of the prefix in seconds. |
| * |
| * @param[in] aPreferredLifetime The preferred lifetime in seconds. |
| */ |
| void SetPreferredLifetime(uint32_t aPreferredLifetime) |
| { |
| mPreferredLifetime = BigEndian::HostSwap32(aPreferredLifetime); |
| } |
| |
| /** |
| * THis method returns the preferred lifetime of the prefix in seconds. |
| * |
| * @returns The preferred lifetime in seconds. |
| */ |
| uint32_t GetPreferredLifetime(void) const { return BigEndian::HostSwap32(mPreferredLifetime); } |
| |
| /** |
| * Returns the prefix length (in bits). |
| * |
| * @returns The prefix length (in bits). |
| */ |
| uint8_t GetPrefixLength(void) const { return mPrefixLength; } |
| |
| /** |
| * Sets the prefix length (in bits). |
| * |
| * @param[in] aPrefixLength The prefix length (in bits). |
| */ |
| void SetPrefixLength(uint8_t aPrefixLength) { mPrefixLength = aPrefixLength; } |
| |
| /** |
| * Sets the prefix. |
| * |
| * @param[in] aPrefix The prefix contained in this option. |
| */ |
| void SetPrefix(const Prefix &aPrefix); |
| |
| /** |
| * Gets the prefix in this option. |
| * |
| * @param[out] aPrefix Reference to a `Prefix` to return the prefix. |
| */ |
| void GetPrefix(Prefix &aPrefix) const; |
| |
| /** |
| * Indicates whether or not the option is valid. |
| * |
| * @retval TRUE The option is valid |
| * @retval FALSE The option is not valid. |
| */ |
| bool IsValid(void) const; |
| |
| PrefixInfoOption(void) = delete; |
| |
| private: |
| // Prefix Information Option |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Length | Prefix Length |L|A|R|P| Rsvd1 | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Valid Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Preferred Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Reserved2 | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | | |
| // + + |
| // | | |
| // + Prefix + |
| // | | |
| // + + |
| // | | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // |
| // Reference for P Flag (DHCPv6-PD preferred flag): |
| // https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-6man-pio-pflag.xml |
| |
| uint8_t mPrefixLength; // The prefix length in bits. |
| uint8_t mFlags; // The flags field. |
| uint32_t mValidLifetime; // The valid lifetime of the prefix. |
| uint32_t mPreferredLifetime; // The preferred lifetime of the prefix. |
| uint32_t mReserved2; // The reserved field. |
| Address mPrefix; // The prefix. |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure"); |
| |
| /** |
| * Represents the Route Information Option. |
| * |
| * See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3] |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class RouteInfoOption : public Option, private Clearable<RouteInfoOption> |
| { |
| friend class Clearable<RouteInfoOption>; |
| |
| public: |
| static constexpr uint16_t kMinSize = kLengthUnit; ///< Minimum size (in bytes) of a Route Info Option |
| static constexpr Type kType = kTypeRouteInfo; ///< Route Information Option Type. |
| |
| /** |
| * Initializes the option setting the type and clearing (setting to zero) all other fields. |
| */ |
| void Init(void); |
| |
| /** |
| * Sets the route preference. |
| * |
| * @param[in] aPreference The route preference. |
| */ |
| void SetPreference(RoutePreference aPreference); |
| |
| /** |
| * Gets the route preference. |
| * |
| * @returns The route preference. |
| */ |
| RoutePreference GetPreference(void) const; |
| |
| /** |
| * Sets the lifetime of the route in seconds. |
| * |
| * @param[in] aLifetime The lifetime of the route in seconds. |
| */ |
| void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = BigEndian::HostSwap32(aLifetime); } |
| |
| /** |
| * Gets Route Lifetime in seconds. |
| * |
| * @returns The Route Lifetime in seconds. |
| */ |
| uint32_t GetRouteLifetime(void) const { return BigEndian::HostSwap32(mRouteLifetime); } |
| |
| /** |
| * Sets the prefix and adjusts the option length based on the prefix length. |
| * |
| * @param[in] aPrefix The prefix contained in this option. |
| */ |
| void SetPrefix(const Prefix &aPrefix); |
| |
| /** |
| * Gets the prefix in this option. |
| * |
| * @param[out] aPrefix Reference to a `Prefix` to return the prefix. |
| */ |
| void GetPrefix(Prefix &aPrefix) const; |
| |
| /** |
| * Tells whether this option is valid. |
| * |
| * @returns A boolean indicates whether this option is valid. |
| */ |
| bool IsValid(void) const; |
| |
| /** |
| * Calculates the minimum option length for a given prefix length. |
| * |
| * The option length (which is in unit of 8 octets) can be 1, 2, or 3 depending on the prefix length. It can be 1 |
| * for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise. |
| * |
| * @param[in] aPrefixLength The prefix length (in bits). |
| * |
| * @returns The option length (in unit of 8 octet) for @p aPrefixLength. |
| */ |
| static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength); |
| |
| /** |
| * Calculates the minimum option size (in bytes) for a given prefix length. |
| * |
| * @param[in] aPrefixLength The prefix length (in bits). |
| * |
| * @returns The option size (in bytes) for @p aPrefixLength. |
| */ |
| static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength) |
| { |
| return kLengthUnit * OptionLengthForPrefix(aPrefixLength); |
| } |
| |
| RouteInfoOption(void) = delete; |
| |
| private: |
| // Route Information Option |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Length | Prefix Length |Resvd|Prf|Resvd| |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Route Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Prefix (Variable Length) | |
| // . . |
| // . . |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| static constexpr uint8_t kPreferenceOffset = 3; |
| static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset; |
| |
| uint8_t *GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); } |
| const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); } |
| |
| uint8_t mPrefixLength; // The prefix length in bits. |
| uint8_t mResvdPrf; // The preference. |
| uint32_t mRouteLifetime; // The lifetime in seconds. |
| // Followed by prefix bytes (variable length). |
| |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure"); |
| |
| /** |
| * Represents an RA Flags Extension Option. |
| * |
| * See RFC-5175 [https://tools.ietf.org/html/rfc5175] |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class RaFlagsExtOption : public Option, private Clearable<RaFlagsExtOption> |
| { |
| friend class Clearable<RaFlagsExtOption>; |
| |
| public: |
| static constexpr Type kType = kTypeRaFlagsExtension; ///< RA Flags Extension Option type. |
| |
| /** |
| * Initializes the RA Flags Extension option with proper type and length and sets all flags to zero. |
| */ |
| void Init(void); |
| |
| /** |
| * Tells whether this option is valid. |
| * |
| * @returns A boolean indicates whether this option is valid. |
| */ |
| bool IsValid(void) const { return GetSize() >= sizeof(*this); } |
| |
| RaFlagsExtOption(void) = delete; |
| |
| private: |
| // RA Flags Extension Option |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Length | Bit fields available .. |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // ... for assignment | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . |
| |
| uint8_t mFlags[6]; |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(RaFlagsExtOption) == 8, "invalid RaFlagsExtOption structure"); |
| |
| /** |
| * Represents the NAT64 Prefix Option (aka PREF64 Option). |
| * |
| * See section 4 of RFC 8781 for definition of this option [https://tools.ietf.org/html/rfc8781#section-4] |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class Nat64PrefixOption : public Option, private Clearable<Nat64PrefixOption> |
| { |
| friend class Clearable<Nat64PrefixOption>; |
| |
| public: |
| static constexpr Type kType = kTypeNat64Prefix; ///< NAT64 Prefix Option Type. |
| |
| /** |
| * Initializes the NAT64 Prefix option with proper type and length and sets all other fields to zero. |
| */ |
| void Init(void); |
| |
| /** |
| * Sets the NAT64 prefix lifetime. |
| * |
| * @param[in] aLifetime The prefix lifetime in seconds. |
| */ |
| void SetLifetime(uint32_t aLifetime); |
| |
| /** |
| * Returns the NAT64 prefix lifetime in seconds. |
| * |
| * The NAT64 prefix lifetime is encoded by scaled lifetime in units of 8 seconds. |
| * |
| * @returns The prefix lifetime in seconds. |
| */ |
| uint32_t GetLifetime(void) const |
| { |
| return (BigEndian::HostSwap16(mPrefixAttr) >> kScaledLifetimeOffset) * kLifetimeScalingUnit; |
| } |
| |
| /** |
| * Sets the prefix. |
| * |
| * @param[in] aPrefix The prefix contained in this option. |
| * |
| * @retval kErrorNone Successfully set the prefix. |
| * @retval kErrorInvalidArgs The prefix length in @p aPrefix is not a valid NAT64 prefix length (must be one of |
| * 32, 40, 48, 56, 64, or 96). |
| */ |
| Error SetPrefix(const Prefix &aPrefix); |
| |
| /** |
| * Gets the prefix in this option. |
| * |
| * @param[out] aPrefix Reference to a `Prefix` to return the prefix. |
| * |
| * @retval kErrorNone Successfully retrieved the prefix. |
| * @retval kErrorParse The Prefix Length Code is not valid. |
| */ |
| Error GetPrefix(Prefix &aPrefix) const; |
| |
| /** |
| * Indicates whether or not the option is valid. |
| * |
| * @retval TRUE The option is valid |
| * @retval FALSE The option is not valid. |
| */ |
| bool IsValid(void) const; |
| |
| Nat64PrefixOption(void) = delete; |
| |
| private: |
| // NAT64 Prefix Option |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Length | Scaled Lifetime | PLC | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | | |
| // + + |
| // | Highest 96 bits of the Prefix | |
| // + + |
| // | | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| static constexpr uint32_t kLifetimeScalingUnit = 8; // Lifetime is scaled in units of 8 seconds. |
| static constexpr uint16_t kScaledLifetimeOffset = 3; // Scaled Lifetime offset in `mPrefixAttr`. |
| static constexpr uint16_t kPrefixLengthCodeMask = 0x07; // Prefix Length Code mask in `mPrefixAttr`. |
| |
| static const uint8_t kPrefixLengths[]; // Map from prefix length code to prefix length in bits. |
| |
| /** |
| * Returns the NAT64 prefix length code. |
| * |
| * The prefix length code values 0, 1, 2, 3, 4, and 5 indicate the NAT64 prefix length of 96, 64, 56, 48, 40, and 32 |
| * bits, respectively. |
| * |
| * @returns The prefix length code. |
| */ |
| uint8_t GetPrefixLengthCode(void) const { return BigEndian::HostSwap16(mPrefixAttr) & kPrefixLengthCodeMask; } |
| |
| /** |
| * Sets the NAT64 prefix length code. |
| * |
| * @param[in] aPrefixLengthCode The prefix length code. |
| */ |
| void SetPrefixLengthCode(const uint8_t aPrefixLengthCode); |
| |
| uint16_t mPrefixAttr; // The prefix attributes (Scaled Lifetime and Prefix Length Code). |
| uint8_t mPrefixMsb[12]; |
| |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(Nat64PrefixOption) == 16, "invalid Nat64PrefixOption structure"); |
| |
| /** |
| * Represents the Recursive DNS Server (RDNSS) Option. |
| * |
| * See section 5.1 of RFC 8106 [https://datatracker.ietf.org/doc/html/rfc8106#section-5.1]. |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class RecursiveDnsServerOption : public Option, private Clearable<RecursiveDnsServerOption> |
| { |
| friend class Clearable<RecursiveDnsServerOption>; |
| |
| public: |
| static constexpr uint16_t kMinSize = kLengthUnit; ///< Minimum size (in bytes) of a RDNSS Option. |
| static constexpr Type kType = kTypeRecursiveDnsServer; ///< Route Information Option Type. |
| |
| /** |
| * Initializes the option setting the type and clearing (setting to zero) all other fields. |
| */ |
| void Init(void); |
| |
| /** |
| * Tells whether this option is valid. |
| * |
| * @returns A boolean indicates whether this option is valid. |
| */ |
| bool IsValid(void) const { return (GetLength() > 0); } |
| |
| /** |
| * Sets the Lifetime field. |
| * |
| * @param[in] aLifetime The lifetime in seconds. |
| */ |
| void SetLifetime(uint32_t aLifetime) { mLifetime = BigEndian::HostSwap32(aLifetime); } |
| |
| /** |
| * Gets the Lifetime fields |
| * |
| * @returns The Lifetime in seconds. |
| */ |
| uint32_t GetLifetime(void) const { return BigEndian::HostSwap32(mLifetime); } |
| |
| /** |
| * Gets the numbers of IPv6 addresses. |
| * |
| * @returns Number of IPv6 addresses. |
| */ |
| uint16_t GetNumAddresses(void) const { return IsValid() ? (GetLength() - 1) / 2 : 0; } |
| |
| /** |
| * Returns a pointer to array of IPv6 addresses of DNS server. |
| * |
| * @returns A pointer to the array of IPv6 addresses. |
| */ |
| const Address *GetAddresses(void) const |
| { |
| return reinterpret_cast<const Address *>(reinterpret_cast<const uint8_t *>(this) + sizeof(*this)); |
| } |
| |
| /** |
| * Returns a pointer to array of IPv6 addresses of DNS server. |
| * |
| * @returns A pointer to the array of IPv6 addresses. |
| */ |
| Address *GetAddresses(void) { return AsNonConst(AsConst(this)->GetAddresses()); } |
| |
| /** |
| * Returns the IPv6 address at a given index. |
| * |
| * Caller MUST ensure that @p aIndex is valid and smaller than `GetNumberOfAddresses()`. Otherwise the behavior |
| * of this method is undefined. |
| * |
| * @param[in] aIndex The index. |
| * |
| * @returns The IPv6 address at @p aIndex. |
| */ |
| const Address &GetAddressAt(uint16_t aIndex) const { return GetAddresses()[aIndex]; } |
| |
| /** |
| * Calculates the option length for a given number of IPv6 addresses. |
| * |
| * @param[in] aNumAddresses Number of IPv6 addresses |
| * |
| * @returns The option length (in unit of 8 octets) for @p aNumAddresses. |
| */ |
| static uint8_t OptionLengthFor(uint8_t aNumAddresses); |
| |
| RecursiveDnsServerOption(void) = delete; |
| |
| private: |
| // RDNSS Option |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Length | Reserved | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | | |
| // : Addresses of IPv6 Recursive DNS Servers : |
| // | | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| uint16_t mReserved; |
| uint32_t mLifetime; |
| // Followed by IPv6 Addresses of DNS servers (variable length). |
| |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(RecursiveDnsServerOption) == 8, "invalid RecursiveDnsServerOption structure"); |
| |
| /** |
| * Defines the ND6 Tx Message. |
| */ |
| class TxMessage |
| { |
| public: |
| /** |
| * Gets the prepared ND6 message as an `Icmp6Packet`. |
| * |
| * @param[out] aPacket A reference to an `Icmp6Packet`. |
| */ |
| void GetAsPacket(Icmp6Packet &aPacket) const { aPacket.Init(mArray.AsCArray(), mArray.GetLength()); } |
| |
| /** |
| * Appends bytes from a given buffer to the ND6 message. |
| * |
| * @param[in] aBytes A pointer to the buffer containing the bytes to append. |
| * @param[in] aLength The buffer length. |
| * |
| * @retval kErrorNone Bytes are appended successfully. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendBytes(const uint8_t *aBytes, uint16_t aLength); |
| |
| /** |
| * Appends a Source/Target Link Layer Address Option to the ND6 message. |
| * |
| * @param[in] aLinkLayerAddress The AIL Layer Address. |
| * @param[in] aType The type of Link Layer Address Option, Source or Target |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendLinkLayerOption(LinkLayerAddress &aLinkLayerAddress, Option::Type aType); |
| |
| /** |
| * Appends an object to the ND6 message. |
| * |
| * @tparam ObjectType The object type to append to the message. |
| * |
| * @param[in] aObject A reference to the object to append to the message. |
| * |
| * @retval kErrorNone Successfully appended the object. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| template <typename ObjectType> Error Append(const ObjectType &aObject) |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| return AppendBytes(reinterpret_cast<const uint8_t *>(&aObject), sizeof(ObjectType)); |
| } |
| |
| protected: |
| static constexpr uint16_t kCapacityIncrement = 256; |
| |
| Option *AppendOption(uint16_t aOptionSize); |
| |
| Heap::Array<uint8_t, kCapacityIncrement> mArray; |
| }; |
| |
| /** |
| * Defines Router Advertisement components. |
| */ |
| class RouterAdvert |
| { |
| public: |
| /** |
| * Represent an RA message header. |
| * |
| * See section 2.2 of RFC 4191 [https://datatracker.ietf.org/doc/html/rfc4191] |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class Header : public Equatable<Header>, public Clearable<Header> |
| { |
| friend class Clearable<Header>; |
| |
| public: |
| /** |
| * Initializes the Router Advertisement message with |
| * zero router lifetime, reachable time and retransmission timer. |
| */ |
| Header(void) { SetToDefault(); } |
| |
| /** |
| * Indicates whether the header is valid by checking the type field to match Router Advertisement ICMPv6 type. |
| * |
| * @retval TRUE The header is valid. |
| * @retval FALSE The header is not valid. |
| */ |
| bool IsValid(void) const { return GetType() == Icmp::Header::kTypeRouterAdvert; } |
| |
| /** |
| * Sets the RA message to default values. |
| */ |
| void SetToDefault(void); |
| |
| /** |
| * Sets the checksum value. |
| * |
| * @param[in] aChecksum The checksum value. |
| */ |
| void SetChecksum(uint16_t aChecksum) { mChecksum = BigEndian::HostSwap16(aChecksum); } |
| |
| /** |
| * Sets the Router Lifetime in seconds. |
| * |
| * @param[in] aRouterLifetime The router lifetime in seconds. |
| */ |
| void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = BigEndian::HostSwap16(aRouterLifetime); } |
| |
| /** |
| * Gets the Router Lifetime (in seconds). |
| * |
| * Router Lifetime set to zero indicates that the sender is not a default router. |
| * |
| * @returns The router lifetime in seconds. |
| */ |
| uint16_t GetRouterLifetime(void) const { return BigEndian::HostSwap16(mRouterLifetime); } |
| |
| /** |
| * Sets the default router preference. |
| * |
| * @param[in] aPreference The router preference. |
| */ |
| void SetDefaultRouterPreference(RoutePreference aPreference); |
| |
| /** |
| * Gets the default router preference. |
| * |
| * @returns The router preference. |
| */ |
| RoutePreference GetDefaultRouterPreference(void) const; |
| |
| /** |
| * Indicates whether or not the Managed Address Config Flag is set in the RA message header. |
| * |
| * @retval TRUE The Managed Address Config Flag is set. |
| * @retval FALSE The Managed Address Config Flag is not set. |
| */ |
| bool IsManagedAddressConfigFlagSet(void) const { return (mFlags & kManagedAddressConfigFlag) != 0; } |
| |
| /** |
| * Sets the Managed Address Config Flag in the RA message. |
| */ |
| void SetManagedAddressConfigFlag(void) { mFlags |= kManagedAddressConfigFlag; } |
| |
| /** |
| * Indicates whether or not the Other Config Flag is set in the RA message header. |
| * |
| * @retval TRUE The Other Config Flag is set. |
| * @retval FALSE The Other Config Flag is not set. |
| */ |
| bool IsOtherConfigFlagSet(void) const { return (mFlags & kOtherConfigFlag) != 0; } |
| |
| /** |
| * Sets the Other Config Flag in the RA message. |
| */ |
| void SetOtherConfigFlag(void) { mFlags |= kOtherConfigFlag; } |
| |
| /** |
| * Indicates whether or not the SNAC Router Flag is set in the RA message header. |
| * |
| * @retval TRUE The SNAC Router Flag is set. |
| * @retval FALSE The SNAC Router Flag is not set. |
| */ |
| bool IsSnacRouterFlagSet(void) const { return (mFlags & kSnacRouterFlag) != 0; } |
| |
| /** |
| * Sets the SNAC Router Flag in the RA message header. |
| */ |
| void SetSnacRouterFlag(void) { mFlags |= kSnacRouterFlag; } |
| |
| /** |
| * This method returns the ICMPv6 message type. |
| * |
| * @returns The ICMPv6 message type. |
| */ |
| Icmp::Header::Type GetType(void) const { return static_cast<Icmp::Header::Type>(mType); } |
| |
| private: |
| // Router Advertisement Message |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Code | Checksum | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Cur Hop Limit |M|O| |Prf| |S| | Router Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Reachable Time | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Retrans Timer | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Options ... |
| // +-+-+-+-+-+-+-+-+-+-+-+- |
| |
| static constexpr uint8_t kManagedAddressConfigFlag = 1 << 7; |
| static constexpr uint8_t kOtherConfigFlag = 1 << 6; |
| static constexpr uint8_t kSnacRouterFlag = 1 << 1; |
| static constexpr uint8_t kPreferenceOffset = 3; |
| static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset; |
| |
| uint8_t mType; |
| uint8_t mCode; |
| uint16_t mChecksum; |
| uint8_t mCurHopLimit; |
| uint8_t mFlags; |
| uint16_t mRouterLifetime; |
| uint32_t mReachableTime; |
| uint32_t mRetransTimer; |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(Header) == 16, "Invalid RA `Header`"); |
| |
| /** |
| * Represents a received RA message. |
| */ |
| class RxMessage |
| { |
| public: |
| /** |
| * Initializes the RA message from a received packet data buffer. |
| * |
| * @param[in] aPacket A received packet data. |
| */ |
| explicit RxMessage(const Icmp6Packet &aPacket) |
| : mData(aPacket) |
| { |
| } |
| |
| /** |
| * Gets the RA message as an `Icmp6Packet`. |
| * |
| * @returns The RA message as an `Icmp6Packet`. |
| */ |
| const Icmp6Packet &GetAsPacket(void) const { return mData; } |
| |
| /** |
| * Indicates whether or not the received RA message is valid. |
| * |
| * @retval TRUE If the RA message is valid. |
| * @retval FALSE If the RA message is not valid. |
| */ |
| bool IsValid(void) const |
| { |
| return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)) && |
| (GetHeader().GetType() == Icmp::Header::kTypeRouterAdvert); |
| } |
| |
| /** |
| * Gets the RA message's header. |
| * |
| * @returns The RA message's header. |
| */ |
| const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); } |
| |
| /** |
| * Indicates whether or not the received RA message contains any options. |
| * |
| * @retval TRUE If the RA message contains at least one option. |
| * @retval FALSE If the RA message contains no options. |
| */ |
| bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); } |
| |
| /** |
| * Returns pointer to the start of option bytes (after header). |
| * |
| * @returns Pointer to start of options. |
| */ |
| const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); } |
| |
| /** |
| * Gets the length (number of bytes) of options. |
| * |
| * @returns Number of bytes after header specifying RA options. |
| */ |
| uint16_t GetOptionLength(void) const { return ContainsAnyOptions() ? mData.GetLength() - sizeof(Header) : 0; } |
| |
| // The following methods are intended to support range-based `for` |
| // loop iteration over `Option`s in the RA message. |
| |
| Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); } |
| Option::Iterator end(void) const { return Option::Iterator(); } |
| |
| private: |
| const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); } |
| |
| Data<kWithUint16Length> mData; |
| }; |
| |
| /** |
| * Represents an RA message to be sent. |
| */ |
| class TxMessage : public ot::Ip6::Nd::TxMessage |
| { |
| public: |
| /** |
| * Appends a Prefix Info Option to the RA message. |
| * |
| * @param[in] aPrefix The prefix. |
| * @param[in] aValidLifetime The valid lifetime in seconds. |
| * @param[in] aPreferredLifetime The preferred lifetime in seconds. |
| * @param[in] aFlags The PIO flags to use. |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendPrefixInfoOption(const Prefix &aPrefix, |
| uint32_t aValidLifetime, |
| uint32_t aPreferredLifetime, |
| PrefixInfoOption::Flags aFlags); |
| |
| /** |
| * Appends a Route Info Option to the RA message. |
| * |
| * @param[in] aPrefix The prefix. |
| * @param[in] aRouteLifetime The route lifetime in seconds. |
| * @param[in] aPreference The route preference. |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference); |
| |
| /** |
| * Appends a NAT64 Prefix Option to the RA message. |
| * |
| * @note This is intended for testing only. An OTBR should not advertise a NAT64 prefix option; it should only |
| * process received ones. |
| * |
| * @param[in] aPrefix The prefix. |
| * @param[in] aLifetime The lifetime in seconds. |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorInvalidArgs Unsupported length for NAT64 prefix. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendNat64PrefixOption(const Prefix &aPrefix, uint32_t aLifetime); |
| |
| /** |
| * Append a Recursive DNS Server Option to the RA message. |
| * |
| * @note This is intended for testing only. An OTBR should not advertise an RDNSS option; it should only |
| * process received ones. |
| * |
| * @param[in] aAddresses A pointer to an array of IPv6 addresses. |
| * @param[in] aNumAddresses Number of addresses in @p aAddresses array. |
| * @param[in] aLifetime The lifetime in seconds. |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendRecursiveDnsServerOption(const Address *aAddresses, uint8_t aNumAddresses, uint32_t aLifetime); |
| |
| /** |
| * Indicates whether or not the received RA message contains any options. |
| * |
| * @retval TRUE If the RA message contains at least one option. |
| * @retval FALSE If the RA message contains no options. |
| */ |
| bool ContainsAnyOptions(void) const { return (mArray.GetLength() > sizeof(Header)); } |
| }; |
| |
| RouterAdvert(void) = delete; |
| }; |
| |
| /** |
| * Implements the Router Solicitation message. |
| * |
| * See section 4.1 of RFC 4861 for definition of this message. |
| * https://tools.ietf.org/html/rfc4861#section-4.1 |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class RouterSolicitHeader |
| { |
| public: |
| /** |
| * Initializes the Router Solicitation message. |
| */ |
| RouterSolicitHeader(void); |
| |
| private: |
| Icmp::Header mHeader; // The common ICMPv6 header. |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(RouterSolicitHeader) == 8, "invalid RouterSolicitHeader structure"); |
| /** |
| * Represents a Neighbor Solicitation (NS) message. |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class NeighborSolicitHeader : public Clearable<NeighborSolicitHeader> |
| { |
| public: |
| /** |
| * Initializes the Neighbor Solicitation message header. |
| */ |
| NeighborSolicitHeader(void); |
| |
| /** |
| * Indicates whether the Neighbor Solicitation message is valid (proper Type and Code). |
| * |
| * @retval TRUE If the message header is valid. |
| * @retval FALSE If the message header is not valid. |
| */ |
| bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborSolicit) && (mCode == 0); } |
| |
| /** |
| * Gets the Target Address field. |
| * |
| * @returns The Target Address. |
| */ |
| const Address &GetTargetAddress(void) const { return mTargetAddress; } |
| |
| /** |
| * Sets the Target Address field. |
| * |
| * @param[in] aTargetAddress The Target Address. |
| */ |
| void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; } |
| |
| private: |
| // Neighbor Solicitation Message (RFC 4861) |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Code | Checksum | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Reserved | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | | |
| // + + |
| // | | |
| // + Target Address + |
| // | | |
| // + + |
| // | | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Options ... |
| // +-+-+-+-+-+-+-+-+-+-+-+- |
| |
| uint8_t mType; |
| uint8_t mCode; |
| uint16_t mChecksum; |
| uint32_t mReserved; |
| Address mTargetAddress; |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(NeighborSolicitHeader) == 24, "Invalid NeighborSolicitHeader definition"); |
| |
| /** |
| * Represents a Neighbor Advertisement (NA) message. |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class NeighborAdvertMessage : public Clearable<NeighborAdvertMessage> |
| { |
| public: |
| NeighborAdvertMessage(void); |
| |
| /** |
| * Indicates whether the Neighbor Advertisement message is valid (proper Type and Code). |
| * |
| * @retval TRUE If the message is valid. |
| * @retval FALSE If the message is not valid. |
| */ |
| bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborAdvert) && (mCode == 0); } |
| |
| /** |
| * Indicates whether or not the Router Flag is set in the NA message. |
| * |
| * @retval TRUE The Router Flag is set. |
| * @retval FALSE The Router Flag is not set. |
| */ |
| bool IsRouterFlagSet(void) const { return (mFlags & kRouterFlag) != 0; } |
| |
| /** |
| * Sets the Router Flag in the NA message. |
| */ |
| void SetRouterFlag(void) { mFlags |= kRouterFlag; } |
| |
| /** |
| * Indicates whether or not the Solicited Flag is set in the NA message. |
| * |
| * @retval TRUE The Solicited Flag is set. |
| * @retval FALSE The Solicited Flag is not set. |
| */ |
| bool IsSolicitedFlagSet(void) const { return (mFlags & kSolicitedFlag) != 0; } |
| |
| /** |
| * Sets the Solicited Flag in the NA message. |
| */ |
| void SetSolicitedFlag(void) { mFlags |= kSolicitedFlag; } |
| |
| /** |
| * Indicates whether or not the Override Flag is set in the NA message. |
| * |
| * @retval TRUE The Override Flag is set. |
| * @retval FALSE The Override Flag is not set. |
| */ |
| bool IsOverrideFlagSet(void) const { return (mFlags & kOverrideFlag) != 0; } |
| |
| /** |
| * Sets the Override Flag in the NA message. |
| */ |
| void SetOverrideFlag(void) { mFlags |= kOverrideFlag; } |
| |
| /** |
| * Gets the Target Address field. |
| * |
| * @returns The Target Address. |
| */ |
| const Address &GetTargetAddress(void) const { return mTargetAddress; } |
| |
| /** |
| * Sets the Target Address field. |
| * |
| * @param[in] aTargetAddress The Target Address. |
| */ |
| void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; } |
| |
| private: |
| // Neighbor Advertisement Message (RFC 4861) |
| // |
| // 0 1 2 3 |
| // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Type | Code | Checksum | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // |R|S|O| Reserved | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | | |
| // + + |
| // | | |
| // + Target Address + |
| // | | |
| // + + |
| // | | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Options ... |
| // +-+-+-+-+-+-+-+-+-+-+-+- |
| |
| static constexpr uint8_t kRouterFlag = (1 << 7); |
| static constexpr uint8_t kSolicitedFlag = (1 << 6); |
| static constexpr uint8_t kOverrideFlag = (1 << 5); |
| |
| uint8_t mType; |
| uint8_t mCode; |
| uint16_t mChecksum; |
| uint8_t mFlags; |
| uint8_t mReserved[3]; |
| Address mTargetAddress; |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(NeighborAdvertMessage) == 24, "Invalid NeighborAdvertMessage definition"); |
| |
| } // namespace Nd |
| } // namespace Ip6 |
| } // namespace ot |
| |
| #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE |
| |
| #endif // OT_CORE_NET_ND6_HPP_ |