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_HPP_ 36 #define MESHCOP_DATASET_HPP_ 37 38 #include "openthread-core-config.h" 39 40 #include <openthread/dataset.h> 41 42 #include "common/as_core_type.hpp" 43 #include "common/clearable.hpp" 44 #include "common/const_cast.hpp" 45 #include "common/locator.hpp" 46 #include "common/message.hpp" 47 #include "common/timer.hpp" 48 #include "common/type_traits.hpp" 49 #include "meshcop/meshcop_tlvs.hpp" 50 #include "thread/mle_types.hpp" 51 52 namespace ot { 53 namespace MeshCoP { 54 55 /** 56 * Represents MeshCop Dataset. 57 * 58 */ 59 class Dataset 60 { 61 friend class DatasetLocal; 62 63 public: 64 static constexpr uint8_t kMaxSize = OT_OPERATIONAL_DATASET_MAX_LENGTH; ///< Max size of MeshCoP Dataset (bytes) 65 static constexpr uint8_t kMaxValueSize = 16; ///< Max size of a TLV value (bytes) 66 static constexpr uint8_t kMaxGetTypes = 64; ///< Max number of types in MGMT_GET.req 67 68 /** 69 * Represents the Dataset type (active or pending). 70 * 71 */ 72 enum Type : uint8_t 73 { 74 kActive, ///< Active Dataset 75 kPending, ///< Pending Dataset 76 }; 77 78 /** 79 * Represents presence of different components in Active or Pending Operational Dataset. 80 * 81 */ 82 class Components : public otOperationalDatasetComponents, public Clearable<Components> 83 { 84 public: 85 /** 86 * Indicates whether or not the Active Timestamp is present in the Dataset. 87 * 88 * @returns TRUE if Active Timestamp is present, FALSE otherwise. 89 * 90 */ IsActiveTimestampPresent(void) const91 bool IsActiveTimestampPresent(void) const { return mIsActiveTimestampPresent; } 92 93 /** 94 * Indicates whether or not the Pending Timestamp is present in the Dataset. 95 * 96 * @returns TRUE if Pending Timestamp is present, FALSE otherwise. 97 * 98 */ IsPendingTimestampPresent(void) const99 bool IsPendingTimestampPresent(void) const { return mIsPendingTimestampPresent; } 100 101 /** 102 * Indicates whether or not the Network Key is present in the Dataset. 103 * 104 * @returns TRUE if Network Key is present, FALSE otherwise. 105 * 106 */ IsNetworkKeyPresent(void) const107 bool IsNetworkKeyPresent(void) const { return mIsNetworkKeyPresent; } 108 109 /** 110 * Indicates whether or not the Network Name is present in the Dataset. 111 * 112 * @returns TRUE if Network Name is present, FALSE otherwise. 113 * 114 */ IsNetworkNamePresent(void) const115 bool IsNetworkNamePresent(void) const { return mIsNetworkNamePresent; } 116 117 /** 118 * Indicates whether or not the Extended PAN ID is present in the Dataset. 119 * 120 * @returns TRUE if Extended PAN ID is present, FALSE otherwise. 121 * 122 */ IsExtendedPanIdPresent(void) const123 bool IsExtendedPanIdPresent(void) const { return mIsExtendedPanIdPresent; } 124 125 /** 126 * Indicates whether or not the Mesh Local Prefix is present in the Dataset. 127 * 128 * @returns TRUE if Mesh Local Prefix is present, FALSE otherwise. 129 * 130 */ IsMeshLocalPrefixPresent(void) const131 bool IsMeshLocalPrefixPresent(void) const { return mIsMeshLocalPrefixPresent; } 132 133 /** 134 * Indicates whether or not the Delay Timer is present in the Dataset. 135 * 136 * @returns TRUE if Delay Timer is present, FALSE otherwise. 137 * 138 */ IsDelayPresent(void) const139 bool IsDelayPresent(void) const { return mIsDelayPresent; } 140 141 /** 142 * Indicates whether or not the PAN ID is present in the Dataset. 143 * 144 * @returns TRUE if PAN ID is present, FALSE otherwise. 145 * 146 */ IsPanIdPresent(void) const147 bool IsPanIdPresent(void) const { return mIsPanIdPresent; } 148 149 /** 150 * Indicates whether or not the Channel is present in the Dataset. 151 * 152 * @returns TRUE if Channel is present, FALSE otherwise. 153 * 154 */ IsChannelPresent(void) const155 bool IsChannelPresent(void) const { return mIsChannelPresent; } 156 157 /** 158 * Indicates whether or not the PSKc is present in the Dataset. 159 * 160 * @returns TRUE if PSKc is present, FALSE otherwise. 161 * 162 */ IsPskcPresent(void) const163 bool IsPskcPresent(void) const { return mIsPskcPresent; } 164 165 /** 166 * Indicates whether or not the Security Policy is present in the Dataset. 167 * 168 * @returns TRUE if Security Policy is present, FALSE otherwise. 169 * 170 */ IsSecurityPolicyPresent(void) const171 bool IsSecurityPolicyPresent(void) const { return mIsSecurityPolicyPresent; } 172 173 /** 174 * Indicates whether or not the Channel Mask is present in the Dataset. 175 * 176 * @returns TRUE if Channel Mask is present, FALSE otherwise. 177 * 178 */ IsChannelMaskPresent(void) const179 bool IsChannelMaskPresent(void) const { return mIsChannelMaskPresent; } 180 }; 181 182 /** 183 * Represents the information about the fields contained an Active or Pending Operational Dataset. 184 * 185 */ 186 class Info : public otOperationalDataset, public Clearable<Info> 187 { 188 public: 189 /** 190 * Indicates whether or not the Active Timestamp is present in the Dataset. 191 * 192 * @returns TRUE if Active Timestamp is present, FALSE otherwise. 193 * 194 */ IsActiveTimestampPresent(void) const195 bool IsActiveTimestampPresent(void) const { return mComponents.mIsActiveTimestampPresent; } 196 197 /** 198 * Gets the Active Timestamp in the Dataset. 199 * 200 * MUST be used when Active Timestamp component is present in the Dataset, otherwise its behavior is 201 * undefined. 202 * 203 * @param[out] aTimestamp A reference to output the Active Timestamp in the Dataset. 204 * 205 */ GetActiveTimestamp(Timestamp & aTimestamp) const206 void GetActiveTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mActiveTimestamp); } 207 208 /** 209 * Sets the Active Timestamp in the Dataset. 210 * 211 * @param[in] aTimestamp A Timestamp value. 212 * 213 */ SetActiveTimestamp(const Timestamp & aTimestamp)214 void SetActiveTimestamp(const Timestamp &aTimestamp) 215 { 216 aTimestamp.ConvertTo(mActiveTimestamp); 217 mComponents.mIsActiveTimestampPresent = true; 218 } 219 220 /** 221 * Indicates whether or not the Pending Timestamp is present in the Dataset. 222 * 223 * @returns TRUE if Pending Timestamp is present, FALSE otherwise. 224 * 225 */ IsPendingTimestampPresent(void) const226 bool IsPendingTimestampPresent(void) const { return mComponents.mIsPendingTimestampPresent; } 227 228 /** 229 * Gets the Pending Timestamp in the Dataset. 230 * 231 * MUST be used when Pending Timestamp component is present in the Dataset, otherwise its behavior 232 * is undefined. 233 * 234 * @param[out] aTimestamp A reference to output the Pending Timestamp in the Dataset. 235 * 236 */ GetPendingTimestamp(Timestamp & aTimestamp) const237 void GetPendingTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mPendingTimestamp); } 238 239 /** 240 * Sets the Pending Timestamp in the Dataset. 241 * 242 * @param[in] aTimestamp A Timestamp value. 243 * 244 */ SetPendingTimestamp(const Timestamp & aTimestamp)245 void SetPendingTimestamp(const Timestamp &aTimestamp) 246 { 247 aTimestamp.ConvertTo(mPendingTimestamp); 248 mComponents.mIsPendingTimestampPresent = true; 249 } 250 251 /** 252 * Indicates whether or not the Network Key is present in the Dataset. 253 * 254 * @returns TRUE if Network Key is present, FALSE otherwise. 255 * 256 */ IsNetworkKeyPresent(void) const257 bool IsNetworkKeyPresent(void) const { return mComponents.mIsNetworkKeyPresent; } 258 259 /** 260 * Gets the Network Key in the Dataset. 261 * 262 * MUST be used when Network Key component is present in the Dataset, otherwise its behavior 263 * is undefined. 264 * 265 * @returns The Network Key in the Dataset. 266 * 267 */ GetNetworkKey(void) const268 const NetworkKey &GetNetworkKey(void) const { return AsCoreType(&mNetworkKey); } 269 270 /** 271 * Sets the Network Key in the Dataset. 272 * 273 * @param[in] aNetworkKey A Network Key. 274 * 275 */ SetNetworkKey(const NetworkKey & aNetworkKey)276 void SetNetworkKey(const NetworkKey &aNetworkKey) 277 { 278 mNetworkKey = aNetworkKey; 279 mComponents.mIsNetworkKeyPresent = true; 280 } 281 282 /** 283 * Returns a reference to the Network Key in the Dataset to be updated by caller. 284 * 285 * @returns A reference to the Network Key in the Dataset. 286 * 287 */ UpdateNetworkKey(void)288 NetworkKey &UpdateNetworkKey(void) 289 { 290 mComponents.mIsNetworkKeyPresent = true; 291 return AsCoreType(&mNetworkKey); 292 } 293 294 /** 295 * Indicates whether or not the Network Name is present in the Dataset. 296 * 297 * @returns TRUE if Network Name is present, FALSE otherwise. 298 * 299 */ IsNetworkNamePresent(void) const300 bool IsNetworkNamePresent(void) const { return mComponents.mIsNetworkNamePresent; } 301 302 /** 303 * Gets the Network Name in the Dataset. 304 * 305 * MUST be used when Network Name component is present in the Dataset, otherwise its behavior is 306 * undefined. 307 * 308 * @returns The Network Name in the Dataset. 309 * 310 */ GetNetworkName(void) const311 const NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); } 312 313 /** 314 * Sets the Network Name in the Dataset. 315 * 316 * @param[in] aNetworkNameData A Network Name Data. 317 * 318 */ SetNetworkName(const NameData & aNetworkNameData)319 void SetNetworkName(const NameData &aNetworkNameData) 320 { 321 IgnoreError(AsCoreType(&mNetworkName).Set(aNetworkNameData)); 322 mComponents.mIsNetworkNamePresent = true; 323 } 324 325 /** 326 * Indicates whether or not the Extended PAN ID is present in the Dataset. 327 * 328 * @returns TRUE if Extended PAN ID is present, FALSE otherwise. 329 * 330 */ IsExtendedPanIdPresent(void) const331 bool IsExtendedPanIdPresent(void) const { return mComponents.mIsExtendedPanIdPresent; } 332 333 /** 334 * Gets the Extended PAN ID in the Dataset. 335 * 336 * MUST be used when Extended PAN ID component is present in the Dataset, otherwise its behavior is 337 * undefined. 338 * 339 * @returns The Extended PAN ID in the Dataset. 340 * 341 */ GetExtendedPanId(void) const342 const ExtendedPanId &GetExtendedPanId(void) const { return AsCoreType(&mExtendedPanId); } 343 344 /** 345 * Sets the Extended PAN ID in the Dataset. 346 * 347 * @param[in] aExtendedPanId An Extended PAN ID. 348 * 349 */ SetExtendedPanId(const ExtendedPanId & aExtendedPanId)350 void SetExtendedPanId(const ExtendedPanId &aExtendedPanId) 351 { 352 mExtendedPanId = aExtendedPanId; 353 mComponents.mIsExtendedPanIdPresent = true; 354 } 355 356 /** 357 * Indicates whether or not the Mesh Local Prefix is present in the Dataset. 358 * 359 * @returns TRUE if Mesh Local Prefix is present, FALSE otherwise. 360 * 361 */ IsMeshLocalPrefixPresent(void) const362 bool IsMeshLocalPrefixPresent(void) const { return mComponents.mIsMeshLocalPrefixPresent; } 363 364 /** 365 * Gets the Mesh Local Prefix in the Dataset. 366 * 367 * MUST be used when Mesh Local Prefix component is present in the Dataset, otherwise its behavior 368 * is undefined. 369 * 370 * @returns The Mesh Local Prefix in the Dataset. 371 * 372 */ GetMeshLocalPrefix(void) const373 const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const 374 { 375 return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix); 376 } 377 378 /** 379 * Sets the Mesh Local Prefix in the Dataset. 380 * 381 * @param[in] aMeshLocalPrefix A Mesh Local Prefix. 382 * 383 */ SetMeshLocalPrefix(const Ip6::NetworkPrefix & aMeshLocalPrefix)384 void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix) 385 { 386 mMeshLocalPrefix = aMeshLocalPrefix; 387 mComponents.mIsMeshLocalPrefixPresent = true; 388 } 389 390 /** 391 * Indicates whether or not the Delay Timer is present in the Dataset. 392 * 393 * @returns TRUE if Delay Timer is present, FALSE otherwise. 394 * 395 */ IsDelayPresent(void) const396 bool IsDelayPresent(void) const { return mComponents.mIsDelayPresent; } 397 398 /** 399 * Gets the Delay Timer in the Dataset. 400 * 401 * MUST be used when Delay Timer component is present in the Dataset, otherwise its behavior is 402 * undefined. 403 * 404 * @returns The Delay Timer in the Dataset. 405 * 406 */ GetDelay(void) const407 uint32_t GetDelay(void) const { return mDelay; } 408 409 /** 410 * Sets the Delay Timer in the Dataset. 411 * 412 * @param[in] aDelay A Delay value. 413 * 414 */ SetDelay(uint32_t aDelay)415 void SetDelay(uint32_t aDelay) 416 { 417 mDelay = aDelay; 418 mComponents.mIsDelayPresent = true; 419 } 420 421 /** 422 * Indicates whether or not the PAN ID is present in the Dataset. 423 * 424 * @returns TRUE if PAN ID is present, FALSE otherwise. 425 * 426 */ IsPanIdPresent(void) const427 bool IsPanIdPresent(void) const { return mComponents.mIsPanIdPresent; } 428 429 /** 430 * Gets the PAN ID in the Dataset. 431 * 432 * MUST be used when PAN ID component is present in the Dataset, otherwise its behavior is 433 * undefined. 434 * 435 * @returns The PAN ID in the Dataset. 436 * 437 */ GetPanId(void) const438 Mac::PanId GetPanId(void) const { return mPanId; } 439 440 /** 441 * Sets the PAN ID in the Dataset. 442 * 443 * @param[in] aPanId A PAN ID. 444 * 445 */ SetPanId(Mac::PanId aPanId)446 void SetPanId(Mac::PanId aPanId) 447 { 448 mPanId = aPanId; 449 mComponents.mIsPanIdPresent = true; 450 } 451 452 /** 453 * Indicates whether or not the Channel is present in the Dataset. 454 * 455 * @returns TRUE if Channel is present, FALSE otherwise. 456 * 457 */ IsChannelPresent(void) const458 bool IsChannelPresent(void) const { return mComponents.mIsChannelPresent; } 459 460 /** 461 * Gets the Channel in the Dataset. 462 * 463 * MUST be used when Channel component is present in the Dataset, otherwise its behavior is 464 * undefined. 465 * 466 * @returns The Channel in the Dataset. 467 * 468 */ GetChannel(void) const469 uint16_t GetChannel(void) const { return mChannel; } 470 471 /** 472 * Sets the Channel in the Dataset. 473 * 474 * @param[in] aChannel A Channel. 475 * 476 */ SetChannel(uint16_t aChannel)477 void SetChannel(uint16_t aChannel) 478 { 479 mChannel = aChannel; 480 mComponents.mIsChannelPresent = true; 481 } 482 483 /** 484 * Indicates whether or not the PSKc is present in the Dataset. 485 * 486 * @returns TRUE if PSKc is present, FALSE otherwise. 487 * 488 */ IsPskcPresent(void) const489 bool IsPskcPresent(void) const { return mComponents.mIsPskcPresent; } 490 491 /** 492 * Gets the PSKc in the Dataset. 493 * 494 * MUST be used when PSKc component is present in the Dataset, otherwise its behavior is undefined. 495 * 496 * @returns The PSKc in the Dataset. 497 * 498 */ GetPskc(void) const499 const Pskc &GetPskc(void) const { return AsCoreType(&mPskc); } 500 501 /** 502 * Set the PSKc in the Dataset. 503 * 504 * @param[in] aPskc A PSKc value. 505 * 506 */ SetPskc(const Pskc & aPskc)507 void SetPskc(const Pskc &aPskc) 508 { 509 mPskc = aPskc; 510 mComponents.mIsPskcPresent = true; 511 } 512 513 /** 514 * Indicates whether or not the Security Policy is present in the Dataset. 515 * 516 * @returns TRUE if Security Policy is present, FALSE otherwise. 517 * 518 */ IsSecurityPolicyPresent(void) const519 bool IsSecurityPolicyPresent(void) const { return mComponents.mIsSecurityPolicyPresent; } 520 521 /** 522 * Gets the Security Policy in the Dataset. 523 * 524 * MUST be used when Security Policy component is present in the Dataset, otherwise its behavior is 525 * undefined. 526 * 527 * @returns The Security Policy in the Dataset. 528 * 529 */ GetSecurityPolicy(void) const530 const SecurityPolicy &GetSecurityPolicy(void) const { return AsCoreType(&mSecurityPolicy); } 531 532 /** 533 * Sets the Security Policy in the Dataset. 534 * 535 * @param[in] aSecurityPolicy A Security Policy to set in Dataset. 536 * 537 */ SetSecurityPolicy(const SecurityPolicy & aSecurityPolicy)538 void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy) 539 { 540 mSecurityPolicy = aSecurityPolicy; 541 mComponents.mIsSecurityPolicyPresent = true; 542 } 543 544 /** 545 * Indicates whether or not the Channel Mask is present in the Dataset. 546 * 547 * @returns TRUE if Channel Mask is present, FALSE otherwise. 548 * 549 */ IsChannelMaskPresent(void) const550 bool IsChannelMaskPresent(void) const { return mComponents.mIsChannelMaskPresent; } 551 552 /** 553 * Gets the Channel Mask in the Dataset. 554 * 555 * MUST be used when Channel Mask component is present in the Dataset, otherwise its behavior is 556 * undefined. 557 * 558 * @returns The Channel Mask in the Dataset. 559 * 560 */ GetChannelMask(void) const561 otChannelMask GetChannelMask(void) const { return mChannelMask; } 562 563 /** 564 * Sets the Channel Mask in the Dataset. 565 * 566 * @param[in] aChannelMask A Channel Mask value. 567 * 568 */ SetChannelMask(otChannelMask aChannelMask)569 void SetChannelMask(otChannelMask aChannelMask) 570 { 571 mChannelMask = aChannelMask; 572 mComponents.mIsChannelMaskPresent = true; 573 } 574 575 /** 576 * Populates the Dataset with random fields. 577 * 578 * The Network Key, PSKc, Mesh Local Prefix, PAN ID, and Extended PAN ID are generated randomly (crypto-secure) 579 * with Network Name set to "OpenThread-%04x" with PAN ID appended as hex. The Channel is chosen randomly from 580 * radio's preferred channel mask, Channel Mask is set from radio's supported mask, and Security Policy Flags 581 * from current `KeyManager` value. 582 * 583 * @param[in] aInstance The OpenThread instance. 584 * 585 * @retval kErrorNone If the Dataset was generated successfully. 586 * 587 */ 588 Error GenerateRandom(Instance &aInstance); 589 590 /** 591 * Checks whether the Dataset is a subset of another one, i.e., all the components in the current 592 * Dataset are also present in the @p aOther and the component values fully match. 593 * 594 * The matching of components in the two Datasets excludes Active/Pending Timestamp and Delay components. 595 * 596 * @param[in] aOther The other Dataset to check against. 597 * 598 * @retval TRUE The current dataset is a subset of @p aOther. 599 * @retval FALSE The current Dataset is not a subset of @p aOther. 600 * 601 */ 602 bool IsSubsetOf(const Info &aOther) const; 603 }; 604 605 /** 606 * Initializes the object. 607 * 608 */ 609 Dataset(void); 610 611 /** 612 * Clears the Dataset. 613 * 614 */ 615 void Clear(void); 616 617 /** 618 * Indicates whether or not the dataset appears to be well-formed. 619 * 620 * @returns TRUE if the dataset appears to be well-formed, FALSE otherwise. 621 * 622 */ 623 bool IsValid(void) const; 624 625 /** 626 * Indicates whether or not a given TLV type is present in the Dataset. 627 * 628 * @param[in] aType The TLV type to check. 629 * 630 * @retval TRUE TLV with @p aType is present in the Dataset. 631 * @retval FALSE TLV with @p aType is not present in the Dataset. 632 * 633 */ ContainsTlv(Tlv::Type aType) const634 bool ContainsTlv(Tlv::Type aType) const { return (FindTlv(aType) != nullptr); } 635 636 /** 637 * Indicates whether or not a given TLV type is present in the Dataset. 638 * 639 * @tparam aTlvType The TLV type to check. 640 * 641 * @retval TRUE TLV of @p aTlvType is present in the Dataset. 642 * @retval FALSE TLV of @p aTlvType is not present in the Dataset. 643 * 644 */ Contains(void) const645 template <typename TlvType> bool Contains(void) const 646 { 647 return ContainsTlv(static_cast<Tlv::Type>(TlvType::kType)); 648 } 649 650 /** 651 * Searches for a given TLV type in the Dataset. 652 * 653 * @param[in] aType The TLV type to find. 654 * 655 * @returns A pointer to the TLV or `nullptr` if not found. 656 * 657 */ FindTlv(Tlv::Type aType)658 Tlv *FindTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->FindTlv(aType)); } 659 660 /** 661 * Searches for a given TLV type in the Dataset. 662 * 663 * @param[in] aType The TLV type to find. 664 * 665 * @returns A pointer to the TLV or `nullptr` if not found. 666 * 667 */ 668 const Tlv *FindTlv(Tlv::Type aType) const; 669 670 /** 671 * Writes a TLV to the Dataset. 672 * 673 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended. 674 * 675 * @param[in] aTlv A reference to the TLV. 676 * 677 * @retval kErrorNone Successfully updated the TLV. 678 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space. 679 * 680 */ 681 Error WriteTlv(const Tlv &aTlv); 682 683 /** 684 * Writes a TLV in the Dataset. 685 * 686 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended. 687 * 688 * @param[in] aType The TLV type. 689 * @param[in] aValue A pointer to a buffer containing the TLV value. 690 * @param[in] aLength The TLV length. 691 * 692 * @retval kErrorNone Successfully updated the TLV. 693 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space. 694 * 695 */ 696 Error WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength); 697 698 /** 699 * Writes a simple TLV in the Dataset. 700 * 701 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended. 702 * 703 * @tparam SimpleTlvType The simple TLV type (must be a sub-class of `SimpleTlvInfo`). 704 * 705 * @param[in] aValue The TLV value. 706 * 707 * @retval kErrorNone Successfully updated the TLV. 708 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space. 709 * 710 */ Write(const typename SimpleTlvType::ValueType & aValue)711 template <typename SimpleTlvType> Error Write(const typename SimpleTlvType::ValueType &aValue) 712 { 713 return WriteTlv(static_cast<Tlv::Type>(SimpleTlvType::kType), &aValue, sizeof(aValue)); 714 } 715 716 /** 717 * Writes a `uint` TLV in the Dataset. 718 * 719 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended. 720 * 721 * @tparam UintTlvType The integer simple TLV type (must be a sub-class of `UintTlvInfo`). 722 * 723 * @param[in] aValue The TLV value. 724 * 725 * @retval kErrorNone Successfully updated the TLV. 726 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space. 727 * 728 */ Write(typename UintTlvType::UintValueType aValue)729 template <typename UintTlvType> Error Write(typename UintTlvType::UintValueType aValue) 730 { 731 typename UintTlvType::UintValueType value = BigEndian::HostSwap(aValue); 732 733 return WriteTlv(static_cast<Tlv::Type>(UintTlvType::kType), &value, sizeof(value)); 734 } 735 736 /** 737 * Removes a TLV from the Dataset. 738 * 739 * If the Dataset does not contain the given TLV type, no action is performed. 740 * 741 * @param[in] aType The TLV type to remove. 742 * 743 */ 744 void RemoveTlv(Tlv::Type aType); 745 746 /** 747 * Returns a pointer to the byte representation of the Dataset. 748 * 749 * @returns A pointer to the byte representation of the Dataset. 750 * 751 */ GetBytes(void)752 uint8_t *GetBytes(void) { return mTlvs; } 753 754 /** 755 * Returns a pointer to the byte representation of the Dataset. 756 * 757 * @returns A pointer to the byte representation of the Dataset. 758 * 759 */ GetBytes(void) const760 const uint8_t *GetBytes(void) const { return mTlvs; } 761 762 /** 763 * Converts the TLV representation to structure representation. 764 * 765 * @param[out] aDatasetInfo A reference to `Info` object to output the Dataset. 766 * 767 */ 768 void ConvertTo(Info &aDatasetInfo) const; 769 770 /** 771 * Converts the TLV representation to structure representation. 772 * 773 * @param[out] aDataset A reference to `otOperationalDatasetTlvs` to output the Dataset. 774 * 775 */ 776 void ConvertTo(otOperationalDatasetTlvs &aDataset) const; 777 778 /** 779 * Returns the Dataset size in bytes. 780 * 781 * @returns The Dataset size in bytes. 782 * 783 */ GetSize(void) const784 uint16_t GetSize(void) const { return mLength; } 785 786 /** 787 * Sets the Dataset size in bytes. 788 * 789 * @param[in] aSize The Dataset size in bytes. 790 * 791 */ SetSize(uint16_t aSize)792 void SetSize(uint16_t aSize) { mLength = aSize; } 793 794 /** 795 * Returns the local time the dataset was last updated. 796 * 797 * @returns The local time the dataset was last updated. 798 * 799 */ GetUpdateTime(void) const800 TimeMilli GetUpdateTime(void) const { return mUpdateTime; } 801 802 /** 803 * Gets the Timestamp (Active or Pending). 804 * 805 * @param[in] aType The type: active or pending. 806 * @param[out] aTimestamp A reference to a `Timestamp` to output the value. 807 * 808 * @retval kErrorNone Timestamp was read successfully. @p aTimestamp is updated. 809 * @retval kErrorNotFound Could not find the requested Timestamp TLV. 810 * 811 */ 812 Error GetTimestamp(Type aType, Timestamp &aTimestamp) const; 813 814 /** 815 * Sets the Timestamp value. 816 * 817 * @param[in] aType The type: active or pending. 818 * @param[in] aTimestamp A Timestamp. 819 * 820 */ 821 void SetTimestamp(Type aType, const Timestamp &aTimestamp); 822 823 /** 824 * Reads the Dataset from a given message and checks that it is well-formed and valid. 825 * 826 * @param[in] aMessage The message to read from. 827 * @param[in] aOffset The offset in @p aMessage to start reading the Dataset TLVs. 828 * @param[in] aLength The dataset length in bytes. 829 * 830 * @retval kErrorNone Successfully read and validated the Dataset. 831 * @retval kErrorParse Could not read or parse the dataset from @p aMessage. 832 * 833 */ 834 Error ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); 835 836 /** 837 * Sets the Dataset using an existing Dataset. 838 * 839 * If this Dataset is an Active Dataset, any Pending Timestamp and Delay Timer TLVs will be omitted in the copy 840 * from @p aDataset. 841 * 842 * @param[in] aType The type of the dataset, active or pending. 843 * @param[in] aDataset The input Dataset. 844 * 845 */ 846 void Set(Type aType, const Dataset &aDataset); 847 848 /** 849 * Sets the Dataset from a given structure representation. 850 * 851 * @param[in] aDatasetInfo The input Dataset as `Dataset::Info`. 852 * 853 * @retval kErrorNone Successfully set the Dataset. 854 * @retval kErrorInvalidArgs Dataset is missing Active and/or Pending Timestamp. 855 * 856 */ 857 Error SetFrom(const Info &aDatasetInfo); 858 859 /** 860 * Sets the Dataset using @p aDataset. 861 * 862 * @param[in] aDataset The input Dataset as otOperationalDatasetTlvs. 863 * 864 */ 865 void SetFrom(const otOperationalDatasetTlvs &aDataset); 866 867 /** 868 * Appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV. 869 * 870 * @param[in] aType The type of the dataset, active or pending. 871 * @param[in] aMessage A message to append to. 872 * 873 * @retval kErrorNone Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV. 874 * @retval kErrorNoBufs Insufficient available buffers to append the message with MLE Dataset TLV. 875 * 876 */ 877 Error AppendMleDatasetTlv(Type aType, Message &aMessage) const; 878 879 /** 880 * Applies the Active or Pending Dataset to the Thread interface. 881 * 882 * @param[in] aInstance A reference to the OpenThread instance. 883 * @param[out] aIsNetworkKeyUpdated A pointer to where to place whether network key was updated. 884 * 885 * @retval kErrorNone Successfully applied configuration. 886 * @retval kErrorParse The dataset has at least one TLV with invalid format. 887 * 888 */ 889 Error ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdated = nullptr) const; 890 891 /** 892 * Converts a Pending Dataset to an Active Dataset. 893 * 894 * Removes the Delay Timer and Pending Timestamp TLVs 895 * 896 */ 897 void ConvertToActive(void); 898 899 /** 900 * Returns a pointer to the start of Dataset TLVs sequence. 901 * 902 * @return A pointer to the start of Dataset TLVs sequence. 903 * 904 */ GetTlvsStart(void)905 Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); } 906 907 /** 908 * Returns a pointer to the start of Dataset TLVs sequence. 909 * 910 * @return A pointer to start of Dataset TLVs sequence. 911 * 912 */ GetTlvsStart(void) const913 const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); } 914 915 /** 916 * Returns a pointer to the past-the-end of Dataset TLVs sequence. 917 * 918 * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence. 919 * 920 * @return A pointer to past-the-end of Dataset TLVs sequence. 921 * 922 */ GetTlvsEnd(void)923 Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); } 924 925 /** 926 * Returns a pointer to the past-the-end of Dataset TLVs sequence. 927 * 928 * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence. 929 * 930 * @return A pointer to past-the-end of Dataset TLVs sequence. 931 * 932 */ GetTlvsEnd(void) const933 const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); } 934 935 /** 936 * Converts a Dataset Type to a string. 937 * 938 * @param[in] aType A Dataset type. 939 * 940 */ 941 static const char *TypeToString(Type aType); 942 943 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 944 945 /** 946 * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero. 947 * 948 * If the Dataset does not contain the @p aTlvType, no action is performed. 949 * 950 * @param[in] aTlvType The TLV type. 951 * @param[in] aKeyRef The `KeyRef` to use with secure storage. 952 * 953 */ 954 void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef); 955 956 /** 957 * Reads and updates a given TLV value in Dataset from secure storage. 958 * 959 * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned. 960 * 961 * @param[in] aTlvType The TLV type. 962 * @param[in] aKeyRef The `KeyRef` to use with secure storage. 963 * 964 * @retval kErrorNone Successfully read the TLV value from secure storage and updated the Dataset. 965 * @retval KErrorFailed Could not read the @aKeyRef from secure storage. 966 * 967 */ 968 Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef); 969 970 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 971 972 private: 973 void RemoveTlv(Tlv *aTlv); 974 975 uint8_t mTlvs[kMaxSize]; ///< The Dataset buffer 976 TimeMilli mUpdateTime; ///< Local time last updated 977 uint16_t mLength; ///< The number of valid bytes in @var mTlvs 978 }; 979 980 } // namespace MeshCoP 981 982 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components); 983 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info); 984 985 } // namespace ot 986 987 #endif // MESHCOP_DATASET_HPP_ 988