| /* |
| * 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 ND6_HPP_ |
| #define ND6_HPP_ |
| |
| #include "openthread-core-config.h" |
| |
| #include <stdint.h> |
| |
| #include <openthread/netdata.h> |
| #include <openthread/platform/toolchain.h> |
| |
| #include "common/const_cast.hpp" |
| #include "common/encoding.hpp" |
| #include "common/equatable.hpp" |
| #include "net/icmp6.hpp" |
| #include "net/ip6.hpp" |
| #include "thread/network_data_types.hpp" |
| |
| using ot::Encoding::BigEndian::HostSwap16; |
| using ot::Encoding::BigEndian::HostSwap32; |
| |
| namespace ot { |
| namespace Ip6 { |
| namespace Nd { |
| |
| typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference |
| |
| /** |
| * Represents the variable length options in Neighbor Discovery messages. |
| * |
| * @sa PrefixInfoOption |
| * @sa RouteInfoOption |
| * |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class Option |
| { |
| friend class RouterAdvertMessage; |
| |
| public: |
| enum Type : uint8_t |
| { |
| kTypePrefixInfo = 3, ///< Prefix Information Option. |
| kTypeRouteInfo = 24, ///< Route Information Option. |
| kTypeRaFlagsExtension = 26, ///< RA Flags Extension 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>((aSize + kLengthUnit - 1) / 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. |
| |
| /** |
| * Initializes the Prefix Info option with proper type and length and sets all other fields to zero. |
| * |
| */ |
| void Init(void); |
| |
| /** |
| * 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 & kOnLinkFlagMask) != 0; } |
| |
| /** |
| * Sets the on-link (L) flag. |
| * |
| */ |
| void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; } |
| |
| /** |
| * Clears the on-link (L) flag. |
| * |
| */ |
| void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; } |
| |
| /** |
| * 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 & kAutoConfigFlagMask) != 0; } |
| |
| /** |
| * Sets the autonomous address-configuration (A) flag. |
| * |
| */ |
| void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; } |
| |
| /** |
| * Clears the autonomous address-configuration (A) flag. |
| * |
| */ |
| void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; } |
| |
| /** |
| * Sets the valid lifetime of the prefix in seconds. |
| * |
| * @param[in] aValidLifetime The valid lifetime in seconds. |
| * |
| */ |
| void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = 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 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 = 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 HostSwap32(mPreferredLifetime); } |
| |
| /** |
| * 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| Reserved1 | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Valid Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Preferred Lifetime | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | Reserved2 | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // | | |
| // + + |
| // | | |
| // + Prefix + |
| // | | |
| // + + |
| // | | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag. |
| static constexpr uint8_t kOnLinkFlagMask = 0x80; // On-link flag. |
| |
| 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 = HostSwap32(aLifetime); } |
| |
| /** |
| * Gets Route Lifetime in seconds. |
| * |
| * @returns The Route Lifetime in seconds. |
| * |
| */ |
| uint32_t GetRouteLifetime(void) const { return 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); } |
| |
| /** |
| * Indicates whether or not the Stub Router Flag is set. |
| * |
| * @retval TRUE The Stub Router Flag is set. |
| * @retval FALSE The Stub Router Flag is not set. |
| * |
| */ |
| bool IsStubRouterFlagSet(void) const { return (mFlags[0] & kStubRouterFlag) != 0; } |
| |
| /** |
| * Sets the Stub Router Flag. |
| * |
| */ |
| void SetStubRouterFlag(void) { mFlags[0] |= kStubRouterFlag; } |
| |
| 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 | |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . |
| |
| // Stub router flags defined in [https://www.ietf.org/archive/id/draft-hui-stub-router-ra-flag-01.txt] |
| |
| static constexpr uint8_t kStubRouterFlag = 1 << 7; |
| |
| uint8_t mFlags[6]; |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(RaFlagsExtOption) == 8, "invalid RaFlagsExtOption structure"); |
| |
| /** |
| * Represents a Router Advertisement message. |
| * |
| */ |
| class RouterAdvertMessage |
| { |
| public: |
| /** |
| * Implements the 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>, private Clearable<Header> |
| { |
| friend class Clearable<Header>; |
| |
| public: |
| /** |
| * Initializes the Router Advertisement message with |
| * zero router lifetime, reachable time and retransmission timer. |
| * |
| */ |
| Header(void) { SetToDefault(); } |
| |
| /** |
| * 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 = HostSwap16(aChecksum); } |
| |
| /** |
| * Sets the Router Lifetime in seconds. |
| * |
| * @param[in] aRouterLifetime The router lifetime in seconds. |
| * |
| */ |
| void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = 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 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; } |
| |
| /** |
| * 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| | 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 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`"); |
| |
| typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet. |
| |
| /** |
| * Initializes the RA message from a received packet data buffer. |
| * |
| * @param[in] aPacket A received packet data. |
| * |
| */ |
| explicit RouterAdvertMessage(const Icmp6Packet &aPacket) |
| : mData(aPacket) |
| , mMaxLength(0) |
| { |
| } |
| |
| /** |
| * This template constructor initializes the RA message with a given header using a given buffer to store the RA |
| * message. |
| * |
| * @tparam kBufferSize The size of the buffer used to store the RA message. |
| * |
| * @param[in] aHeader The RA message header. |
| * @param[in] aBuffer The data buffer to store the RA message in. |
| * |
| */ |
| template <uint16_t kBufferSize> |
| RouterAdvertMessage(const Header &aHeader, uint8_t (&aBuffer)[kBufferSize]) |
| : mMaxLength(kBufferSize) |
| { |
| static_assert(kBufferSize >= sizeof(Header), "Buffer for RA msg is too small"); |
| |
| memcpy(aBuffer, &aHeader, sizeof(Header)); |
| mData.Init(aBuffer, sizeof(Header)); |
| } |
| |
| /** |
| * 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 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()); } |
| |
| /** |
| * Appends a Prefix Info Option to the RA message. |
| * |
| * The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set. |
| * |
| * @param[in] aPrefix The prefix. |
| * @param[in] aValidLifetime The valid lifetime in seconds. |
| * @param[in] aPreferredLifetime The preferred lifetime in seconds. |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorNoBufs No more space in the buffer to append the option. |
| * |
| */ |
| Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime); |
| |
| /** |
| * 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 No more space in the buffer to append the option. |
| * |
| */ |
| Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference); |
| |
| /** |
| * Appends a Flags Extension Option to the RA message. |
| * |
| * @param[in] aStubRouterFlag The stub router flag. |
| * |
| * @retval kErrorNone Option is appended successfully. |
| * @retval kErrorNoBufs No more space in the buffer to append the option. |
| * |
| */ |
| Error AppendFlagsExtensionOption(bool aStubRouterFlag); |
| |
| /** |
| * Indicates whether or not the 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)); } |
| |
| // 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 *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); } |
| const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); } |
| Option *AppendOption(uint16_t aOptionSize); |
| |
| Data<kWithUint16Length> mData; |
| uint16_t mMaxLength; |
| }; |
| |
| /** |
| * 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 RouterSolicitMessage |
| { |
| public: |
| /** |
| * Initializes the Router Solicitation message. |
| * |
| */ |
| RouterSolicitMessage(void); |
| |
| private: |
| Icmp::Header mHeader; // The common ICMPv6 header. |
| } OT_TOOL_PACKED_END; |
| |
| static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure"); |
| |
| /** |
| * Represents a Neighbor Solicitation (NS) message. |
| * |
| */ |
| OT_TOOL_PACKED_BEGIN |
| class NeighborSolicitMessage : public Clearable<NeighborSolicitMessage> |
| { |
| public: |
| /** |
| * Initializes the Neighbor Solicitation message. |
| * |
| */ |
| NeighborSolicitMessage(void); |
| |
| /** |
| * Indicates whether the Neighbor Solicitation 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::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(NeighborSolicitMessage) == 24, "Invalid NeighborSolicitMessage 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 // ND6_HPP_ |