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