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 managing MeshCoP Datasets. 32 * 33 */ 34 35 #ifndef MESHCOP_DATASET_MANAGER_HPP_ 36 #define MESHCOP_DATASET_MANAGER_HPP_ 37 38 #include "openthread-core-config.h" 39 40 #include "common/callback.hpp" 41 #include "common/locator.hpp" 42 #include "common/non_copyable.hpp" 43 #include "common/timer.hpp" 44 #include "mac/channel_mask.hpp" 45 #include "meshcop/dataset.hpp" 46 #include "net/udp6.hpp" 47 #include "thread/tmf.hpp" 48 49 namespace ot { 50 51 namespace MeshCoP { 52 53 class ActiveDatasetManager; 54 class PendingDatasetManager; 55 56 class DatasetManager : public InstanceLocator 57 { 58 friend class ActiveDatasetManager; 59 friend class PendingDatasetManager; 60 61 public: 62 /** 63 * Callback function pointer, invoked when a response to a MGMT_SET request is received or times out. 64 * 65 */ 66 typedef otDatasetMgmtSetCallback MgmtSetCallback; 67 68 /** 69 * Returns the network Timestamp. 70 * 71 * @returns The network Timestamp. 72 * 73 */ GetTimestamp(void) const74 const Timestamp &GetTimestamp(void) const { return mNetworkTimestamp; } 75 76 /** 77 * Clears the Operational Dataset. 78 * 79 */ 80 void Clear(void); 81 82 /** 83 * Restores the Operational Dataset from non-volatile memory. 84 * 85 * @retval kErrorNone Successfully restore the dataset. 86 * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory. 87 * 88 */ 89 Error Restore(void); 90 91 /** 92 * Retrieves the dataset from non-volatile memory. 93 * 94 * @param[out] aDataset Where to place the dataset. 95 * 96 * @retval kErrorNone Successfully retrieved the dataset. 97 * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory. 98 * 99 */ 100 Error Read(Dataset &aDataset) const; 101 102 /** 103 * Retrieves the dataset from non-volatile memory. 104 * 105 * @param[out] aDatasetInfo Where to place the dataset (as `Dataset::Info`). 106 * 107 * @retval kErrorNone Successfully retrieved the dataset. 108 * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory. 109 * 110 */ 111 Error Read(Dataset::Info &aDatasetInfo) const; 112 113 /** 114 * Retrieves the dataset from non-volatile memory. 115 * 116 * @param[out] aDatasetTlvs Where to place the dataset. 117 * 118 * @retval kErrorNone Successfully retrieved the dataset. 119 * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory. 120 * 121 */ 122 Error Read(Dataset::Tlvs &aDatasetTlvs) const; 123 124 /** 125 * Saves the Operational Dataset in non-volatile memory. 126 * 127 * @param[in] aDataset The Operational Dataset. 128 * 129 */ 130 void SaveLocal(const Dataset &aDataset); 131 132 /** 133 * Saves the Operational Dataset in non-volatile memory. 134 * 135 * @param[in] aDatasetInfo The Operational Dataset as `Dataset::Info`. 136 * 137 */ 138 void SaveLocal(const Dataset::Info &aDatasetInfo); 139 140 /** 141 * Saves the Operational Dataset in non-volatile memory. 142 * 143 * @param[in] aDatasetTlvs The Operational Dataset as `Dataset::Tlvs`. 144 * 145 * @retval kErrorNone Successfully saved the dataset. 146 * @retval kErrorInvalidArgs The @p aDatasetTlvs is invalid. It is too long or contains incorrect TLV formatting. 147 * 148 */ 149 Error SaveLocal(const Dataset::Tlvs &aDatasetTlvs); 150 151 /** 152 * Sets the Operational Dataset for the partition. 153 * 154 * Also updates the non-volatile local version if the partition's Operational Dataset is newer. If Active 155 * Operational Dataset is changed, applies the configuration to to Thread interface. 156 * 157 * @param[in] aDataset The Operational Dataset. 158 * 159 * @retval kErrorNone Successfully applied configuration. 160 * @retval kErrorParse The dataset has at least one TLV with invalid format. 161 * 162 */ Save(const Dataset & aDataset)163 Error Save(const Dataset &aDataset) { return Save(aDataset, /* aAllowOlderTimestamp */ false); } 164 165 /** 166 * Sets the Operational Dataset for the partition read from a given message. 167 * 168 * Also updates the non-volatile local version if the partition's Operational Dataset is newer. If Active 169 * Operational Dataset is changed, applies the configuration to to Thread interface. 170 * 171 * @param[in] aTimestamp The timestamp for the Operational Dataset. 172 * @param[in] aMessage The message to read from. 173 * @param[in] aOffset The offset where the Operational Dataset begins. 174 * @param[in] aLength The length of the Operational Dataset. 175 * 176 * @retval kErrorNone Successfully parsed the Dataset from the @p aMessage and saved it. 177 * @retval kErrorParse Could not parse the Dataset from @p aMessage. 178 * 179 */ 180 Error Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint16_t aLength); 181 182 /** 183 * Retrieves the channel mask from local dataset. 184 * 185 * @param[out] aChannelMask A reference to the channel mask. 186 * 187 * @retval kErrorNone Successfully retrieved the channel mask. 188 * @retval kErrorNotFound There is no valid channel mask stored in local dataset. 189 * 190 */ 191 Error GetChannelMask(Mac::ChannelMask &aChannelMask) const; 192 193 /** 194 * Applies the Active or Pending Dataset to the Thread interface. 195 * 196 * @retval kErrorNone Successfully applied configuration. 197 * @retval kErrorParse The dataset has at least one TLV with invalid format. 198 * 199 */ 200 Error ApplyConfiguration(void) const; 201 202 /** 203 * Sends a MGMT_SET request to the Leader. 204 * 205 * @param[in] aDatasetInfo The Operational Dataset. 206 * @param[in] aTlvs Any additional raw TLVs to include. 207 * @param[in] aLength Number of bytes in @p aTlvs. 208 * @param[in] aCallback A pointer to a function that is called on response reception or timeout. 209 * @param[in] aContext A pointer to application-specific context for @p aCallback. 210 * 211 * @retval kErrorNone Successfully send the meshcop dataset command. 212 * @retval kErrorNoBufs Insufficient buffer space to send. 213 * @retval kErrorBusy A previous request is ongoing. 214 * 215 */ 216 Error SendSetRequest(const Dataset::Info &aDatasetInfo, 217 const uint8_t *aTlvs, 218 uint8_t aLength, 219 MgmtSetCallback aCallback, 220 void *aContext); 221 222 /** 223 * Sends a MGMT_GET request. 224 * 225 * @param[in] aDatasetComponents An Operational Dataset components structure specifying components to request. 226 * @param[in] aTlvTypes A pointer to array containing additional raw TLV types to be requested. 227 * @param[in] aLength Number of bytes in @p aTlvTypes. 228 * @param[in] aAddress The IPv6 destination address for the MGMT_GET request. 229 * 230 * @retval kErrorNone Successfully send the meshcop dataset command. 231 * @retval kErrorNoBufs Insufficient buffer space to send. 232 * 233 */ 234 Error SendGetRequest(const Dataset::Components &aDatasetComponents, 235 const uint8_t *aTlvTypes, 236 uint8_t aLength, 237 const otIp6Address *aAddress) const; 238 239 private: 240 static constexpr uint8_t kMaxGetTypes = 64; // Max number of types in MGMT_GET.req 241 static constexpr uint32_t kSendSetDelay = 5000; // in msec. 242 243 using Type = Dataset::Type; 244 245 class TlvList : public Array<uint8_t, kMaxGetTypes> 246 { 247 public: 248 TlvList(void) = default; 249 void Add(uint8_t aTlvType); 250 }; 251 252 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 253 struct SecurelyStoredTlv 254 { GetKeyRefot::MeshCoP::DatasetManager::SecurelyStoredTlv255 Crypto::Storage::KeyRef GetKeyRef(Dataset::Type aType) const 256 { 257 return (aType == Dataset::kActive) ? mActiveKeyRef : mPendingKeyRef; 258 } 259 260 Tlv::Type mTlvType; 261 Crypto::Storage::KeyRef mActiveKeyRef; 262 Crypto::Storage::KeyRef mPendingKeyRef; 263 }; 264 265 static const SecurelyStoredTlv kSecurelyStoredTlvs[]; 266 #endif 267 268 #if OPENTHREAD_FTD 269 enum MgmtCommand : uint8_t 270 { 271 kMgmtSet, 272 kMgmtReplace, 273 }; 274 275 struct RequestInfo : Clearable<RequestInfo> // Info from a MGMT_SET or MGMT_REPLACE request. 276 { 277 Dataset mDataset; 278 bool mIsFromCommissioner; 279 bool mAffectsConnectivity; 280 bool mAffectsNetworkKey; 281 }; 282 #endif 283 284 DatasetManager(Instance &aInstance, Type aType, TimerMilli::Handler aTimerHandler); 285 IsActiveDataset(void) const286 bool IsActiveDataset(void) const { return (mType == Dataset::kActive); } IsPendingDataset(void) const287 bool IsPendingDataset(void) const { return (mType == Dataset::kPending); } 288 void Restore(const Dataset &aDataset); 289 Error ApplyConfiguration(const Dataset &aDataset) const; 290 void HandleGet(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const; 291 void HandleTimer(void); 292 Error Save(const Dataset &aDataset, bool aAllowOlderTimestamp); 293 void LocalSave(const Dataset &aDataset); 294 void SignalDatasetChange(void) const; 295 void SyncLocalWithLeader(const Dataset &aDataset); 296 Error SendSetRequest(const Dataset &aDataset); 297 void SendGetResponse(const Coap::Message &aRequest, 298 const Ip6::MessageInfo &aMessageInfo, 299 const TlvList &aTlvList) const; 300 void HandleMgmtSetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aError); 301 302 static void HandleMgmtSetResponse(void *aContext, 303 otMessage *aMessage, 304 const otMessageInfo *aMessageInfo, 305 Error aError); 306 307 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 308 void MoveKeysToSecureStorage(Dataset &aDataset) const; 309 void DestroySecurelyStoredKeys(void) const; 310 void EmplaceSecurelyStoredKeys(Dataset &aDataset) const; 311 #endif 312 313 #if OPENTHREAD_FTD 314 Error HandleSetOrReplace(MgmtCommand aCommand, const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 315 Error ProcessSetOrReplaceRequest(MgmtCommand aCommand, const Coap::Message &aMessage, RequestInfo &aInfo) const; 316 void SendSetOrReplaceResponse(const Coap::Message &aRequest, 317 const Ip6::MessageInfo &aMessageInfo, 318 StateTlv::State aState); 319 #endif 320 321 Type mType; 322 bool mLocalSaved : 1; 323 bool mMgmtPending : 1; 324 TimeMilli mLocalUpdateTime; 325 Timestamp mLocalTimestamp; 326 Timestamp mNetworkTimestamp; 327 TimerMilli mTimer; 328 Callback<MgmtSetCallback> mMgmtSetCallback; 329 }; 330 331 //---------------------------------------------------------------------------------------------------------------------- 332 333 class ActiveDatasetManager : public DatasetManager, private NonCopyable 334 { 335 friend class Tmf::Agent; 336 337 public: 338 /** 339 * Initializes the ActiveDatasetManager object. 340 * 341 * @param[in] aInstance A reference to the OpenThread instance. 342 * 343 */ 344 explicit ActiveDatasetManager(Instance &aInstance); 345 346 /** 347 * Indicates whether the Active Dataset is partially complete. 348 * 349 * Is primarily used to determine whether a user has supplied a partial Active Dataset for use 350 * with joining a network. 351 * 352 * @retval TRUE If an Active Dataset is saved but does not include an Active Timestamp. 353 * @retval FALSE If an Active Dataset is not saved or does include an Active Timestamp. 354 * 355 */ 356 bool IsPartiallyComplete(void) const; 357 358 /** 359 * Indicates whether the Active Dataset is complete. 360 * 361 * @retval TRUE If an Active Dataset is saved and includes an Active Timestamp. 362 * @retval FALSE If an Active Dataset is not saved or does include an Active Timestamp. 363 * 364 */ 365 bool IsComplete(void) const; 366 367 /** 368 * Indicates whether or not a valid network is present in the Active Operational Dataset. 369 * 370 * @retval TRUE if a valid network is present in the Active Dataset. 371 * @retval FALSE if a valid network is not present in the Active Dataset. 372 * 373 */ 374 bool IsCommissioned(void) const; 375 376 #if OPENTHREAD_FTD 377 378 /** 379 * Creates a new Operational Dataset to use when forming a new network. 380 * 381 * @param[out] aDatasetInfo The Operational Dataset as `Dataset::Info`. 382 * 383 * @retval kErrorNone Successfully created a new Operational Dataset. 384 * @retval kErrorFailed Failed to generate random values for new parameters. 385 * 386 */ CreateNewNetwork(Dataset::Info & aDatasetInfo)387 Error CreateNewNetwork(Dataset::Info &aDatasetInfo) { return aDatasetInfo.GenerateRandom(GetInstance()); } 388 389 /** 390 * Starts the Leader functions for maintaining the Active Operational Dataset. 391 * 392 */ 393 void StartLeader(void); 394 395 #if OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT 396 /** 397 * Generate a default Active Operational Dataset. 398 * 399 * @retval kErrorNone Successfully generated an Active Operational Dataset. 400 * @retval kErrorAlready A valid Active Operational Dataset already exists. 401 * @retval kErrorInvalidState Device is not currently attached to a network. 402 * 403 */ 404 Error GenerateLocal(void); 405 #endif 406 #endif 407 408 private: 409 template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 410 411 static void HandleTimer(Timer &aTimer); HandleTimer(void)412 void HandleTimer(void) { DatasetManager::HandleTimer(); } 413 }; 414 415 DeclareTmfHandler(ActiveDatasetManager, kUriActiveGet); 416 #if OPENTHREAD_FTD 417 DeclareTmfHandler(ActiveDatasetManager, kUriActiveSet); 418 DeclareTmfHandler(ActiveDatasetManager, kUriActiveReplace); 419 #endif 420 421 //---------------------------------------------------------------------------------------------------------------------- 422 423 class PendingDatasetManager : public DatasetManager, private NonCopyable 424 { 425 friend class Tmf::Agent; 426 friend class DatasetManager; 427 428 public: 429 /** 430 * Initializes the PendingDatasetManager object. 431 * 432 * @param[in] aInstance A reference to the OpenThread instance. 433 * 434 */ 435 explicit PendingDatasetManager(Instance &aInstance); 436 437 #if OPENTHREAD_FTD 438 /** 439 * Starts the Leader functions for maintaining the Active Operational Dataset. 440 * 441 */ 442 void StartLeader(void); 443 #endif 444 445 private: 446 #if OPENTHREAD_FTD 447 void ApplyActiveDataset(Dataset &aDataset); 448 #endif 449 450 void StartDelayTimer(void); 451 void StartDelayTimer(const Dataset &aDataset); 452 453 static void HandleTimer(Timer &aTimer); HandleTimer(void)454 void HandleTimer(void) { DatasetManager::HandleTimer(); } 455 456 void HandleDelayTimer(void); 457 template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 458 459 using DelayTimer = TimerMilliIn<PendingDatasetManager, &PendingDatasetManager::HandleDelayTimer>; 460 461 DelayTimer mDelayTimer; 462 }; 463 464 DeclareTmfHandler(PendingDatasetManager, kUriPendingGet); 465 #if OPENTHREAD_FTD 466 DeclareTmfHandler(PendingDatasetManager, kUriPendingSet); 467 #endif 468 469 } // namespace MeshCoP 470 } // namespace ot 471 472 #endif // MESHCOP_DATASET_MANAGER_HPP_ 473