1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for Thread global IPv6 address configuration with SLAAC. 32 */ 33 34 #ifndef SLAAC_ADDRESS_HPP_ 35 #define SLAAC_ADDRESS_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 40 41 #include "common/locator.hpp" 42 #include "common/non_copyable.hpp" 43 #include "common/notifier.hpp" 44 #include "net/netif.hpp" 45 #include "thread/network_data.hpp" 46 47 namespace ot { 48 namespace Utils { 49 50 /** 51 * @addtogroup core-slaac-address 52 * 53 * @brief 54 * This module includes definitions for Thread global IPv6 address configuration with SLAAC. 55 * 56 * @{ 57 */ 58 59 /** 60 * Implements the SLAAC utility for Thread protocol. 61 */ 62 class Slaac : public InstanceLocator, private NonCopyable 63 { 64 friend class ot::Notifier; 65 66 public: 67 typedef otIp6SlaacPrefixFilter PrefixFilter; ///< Prefix filter function pointer. 68 69 /** 70 * Represents the secret key used for generating semantically opaque IID (per RFC 7217). 71 */ 72 struct IidSecretKey 73 { 74 static constexpr uint16_t kSize = 32; ///< Secret key size for generating semantically opaque IID. 75 76 uint8_t m8[kSize]; 77 }; 78 79 /** 80 * Initializes the SLAAC manager object. 81 * 82 * Note that SLAAC module starts enabled. 83 * 84 * @param[in] aInstance A reference to the OpenThread instance. 85 */ 86 explicit Slaac(Instance &aInstance); 87 88 /** 89 * Enables the SLAAC module. 90 * 91 * When enabled, new SLAAC addresses are generated and added from on-mesh prefixes in network data. 92 */ 93 void Enable(void); 94 95 /** 96 * Disables the SLAAC module. 97 * 98 * When disabled, any previously added SLAAC address by this module is removed. 99 */ 100 void Disable(void); 101 102 /** 103 * Indicates whether SLAAC module is enabled or not. 104 * 105 * @retval TRUE SLAAC module is enabled. 106 * @retval FALSE SLAAC module is disabled. 107 */ IsEnabled(void) const108 bool IsEnabled(void) const { return mEnabled; } 109 110 /** 111 * Sets a SLAAC prefix filter handler. 112 * 113 * The handler is invoked by SLAAC module when it is about to add a SLAAC address based on a prefix. The return 114 * boolean value from handler determines whether the address is filtered or added (TRUE to filter the address, 115 * FALSE to add address). 116 * 117 * The filter can be set to `nullptr` to disable filtering (i.e., allow SLAAC addresses for all prefixes). 118 * 119 * @param[in] aFilter The filter to use. 120 */ 121 void SetFilter(PrefixFilter aFilter); 122 123 /** 124 * Generates the IID of an IPv6 address. 125 * 126 * @param[in,out] aAddress A reference to the address that will be filled with the IID generated. 127 * Note the prefix of the address must already be filled and will be used 128 * to generate the IID. 129 * @param[in,out] aDadCounter The DAD_Counter that is employed to resolve Duplicate Address Detection 130 * conflicts. 131 * 132 * @retval kErrorNone If successfully generated the IID. 133 * @retval kErrorFailed If no valid IID was generated. 134 */ 135 Error GenerateIid(Ip6::Netif::UnicastAddress &aAddress, uint8_t &aDadCounter) const; 136 137 /** 138 * Searches in the list of deprecating SLAAC prefixes for a match to a given address and if found, returns the 139 * Domain ID from the Prefix TLV in the Network Data for this SLAAC prefix. 140 * 141 * The `Slaac` module keeps track of the associated Domain IDs for deprecating SLAAC prefixes, even if the related 142 * Prefix TLV has already been removed from the Network Data. This information is used during external route lookup 143 * if a deprecating SLAAC address is used as the source address in an outbound message. 144 * 145 * @param[in] aAddress The address to search for. 146 * @param[out] aDomainId A reference to return the Domain ID. 147 * 148 * @retval kErrorNone Found a match for @p aAddress and updated @p aDomainId. 149 * @retval kErrorNotFound Could not find a match for @p aAddress in deprecating SLAAC prefixes. 150 */ 151 Error FindDomainIdFor(const Ip6::Address &aAddress, uint8_t &aDomainId) const; 152 153 private: 154 static constexpr uint16_t kNumSlaacAddresses = OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES; 155 156 static constexpr uint16_t kMaxIidCreationAttempts = 256; // Maximum number of attempts when generating IID. 157 158 static constexpr uint32_t kDeprecationInterval = 159 TimeMilli::SecToMsec(OPENTHREAD_CONFIG_IP6_SLAAC_DEPRECATION_INTERVAL); 160 161 enum Action : uint8_t 162 { 163 kAdding, 164 kRemoving, 165 kDeprecating, 166 }; 167 168 class SlaacAddress : public Ip6::Netif::UnicastAddress 169 { 170 public: 171 static constexpr uint8_t kInvalidContextId = 0; 172 IsInUse(void) const173 bool IsInUse(void) const { return mValid; } MarkAsNotInUse(void)174 void MarkAsNotInUse(void) { mValid = false; } GetContextId(void) const175 uint8_t GetContextId(void) const { return mContextId; } SetContextId(uint8_t aContextId)176 void SetContextId(uint8_t aContextId) { mContextId = aContextId; } GetDomainId(void) const177 uint8_t GetDomainId(void) const { return mDomainId; } SetDomainId(uint8_t aDomainId)178 void SetDomainId(uint8_t aDomainId) { mDomainId = aDomainId; } IsDeprecating(void) const179 bool IsDeprecating(void) const { return (mExpirationTime.GetValue() != kNotDeprecated); }; MarkAsNotDeprecating(void)180 void MarkAsNotDeprecating(void) { mExpirationTime.SetValue(kNotDeprecated); } GetExpirationTime(void) const181 TimeMilli GetExpirationTime(void) const { return mExpirationTime; } SetExpirationTime(TimeMilli aTime)182 void SetExpirationTime(TimeMilli aTime) 183 { 184 mExpirationTime = aTime; 185 186 if (mExpirationTime.GetValue() == kNotDeprecated) 187 { 188 mExpirationTime.SetValue(kNotDeprecated + 1); 189 } 190 } 191 192 private: 193 static constexpr uint32_t kNotDeprecated = 0; // Special `mExpirationTime` value to indicate not deprecated. 194 195 uint8_t mContextId; 196 uint8_t mDomainId; 197 TimeMilli mExpirationTime; 198 }; 199 200 bool IsSlaac(const NetworkData::OnMeshPrefixConfig &aConfig) const; 201 bool IsFiltered(const NetworkData::OnMeshPrefixConfig &aConfig) const; 202 void RemoveOrDeprecateAddresses(void); 203 void RemoveAllAddresses(void); 204 void AddAddresses(void); 205 void DeprecateAddress(SlaacAddress &aAddress); 206 void RemoveAddress(SlaacAddress &aAddress); 207 void AddAddressFor(const NetworkData::OnMeshPrefixConfig &aConfig); 208 bool UpdateContextIdFor(SlaacAddress &aSlaacAddress); 209 void HandleTimer(void); 210 void GetIidSecretKey(IidSecretKey &aKey) const; 211 void HandleNotifierEvents(Events aEvents); 212 void LogAddress(Action aAction, const SlaacAddress &aAddress); 213 static bool DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aConfig, 214 const Ip6::Netif::UnicastAddress &aAddr); 215 216 using ExpireTimer = TimerMilliIn<Slaac, &Slaac::HandleTimer>; 217 218 bool mEnabled; 219 PrefixFilter mFilter; 220 ExpireTimer mTimer; 221 SlaacAddress mSlaacAddresses[kNumSlaacAddresses]; 222 }; 223 224 /** 225 * @} 226 */ 227 228 } // namespace Utils 229 } // namespace ot 230 231 #endif // OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 232 233 #endif // SLAAC_ADDRESS_HPP_ 234