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 generating and processing Thread Network Data TLVs. 32 */ 33 34 #ifndef NETWORK_DATA_TLVS_HPP_ 35 #define NETWORK_DATA_TLVS_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <openthread/netdata.h> 40 41 #include "common/debug.hpp" 42 #include "common/encoding.hpp" 43 #include "common/equatable.hpp" 44 #include "net/ip6_address.hpp" 45 #include "thread/network_data_types.hpp" 46 47 namespace ot { 48 namespace NetworkData { 49 50 using ot::Encoding::BigEndian::HostSwap16; 51 using ot::Encoding::BigEndian::HostSwap32; 52 53 /** 54 * @addtogroup core-netdata-tlvs 55 * 56 * @brief 57 * This module includes definitions for generating and processing Thread Network Data TLVs. 58 * 59 * @{ 60 * 61 */ 62 63 /** 64 * This class implements Thread Network Data TLV generation and parsing. 65 * 66 */ 67 OT_TOOL_PACKED_BEGIN 68 class NetworkDataTlv 69 { 70 public: 71 /** 72 * Thread Network Data Type values. 73 * 74 */ 75 enum Type : uint8_t 76 { 77 kTypeHasRoute = 0, ///< Has Route TLV 78 kTypePrefix = 1, ///< Prefix TLV 79 kTypeBorderRouter = 2, ///< Border Router TLV 80 kTypeContext = 3, ///< Context TLV 81 kTypeCommissioningData = 4, ///< Commissioning Dataset TLV 82 kTypeService = 5, ///< Service TLV 83 kTypeServer = 6, ///< Server TLV 84 }; 85 86 /** 87 * This method initializes the TLV. 88 * 89 */ Init(void)90 void Init(void) 91 { 92 mType = 0; 93 mLength = 0; 94 } 95 96 /** 97 * This method returns the Type value. 98 * 99 * @returns The Type value. 100 * 101 */ GetType(void) const102 Type GetType(void) const { return static_cast<Type>(mType >> kTypeOffset); } 103 104 /** 105 * This method sets the Type value. 106 * 107 * @param[in] aType The Type value. 108 * 109 */ SetType(Type aType)110 void SetType(Type aType) { mType = (mType & ~kTypeMask) | ((aType << kTypeOffset) & kTypeMask); } 111 112 /** 113 * This method returns the Length value. 114 * 115 * @returns The Length value. 116 * 117 */ GetLength(void) const118 uint8_t GetLength(void) const { return mLength; } 119 120 /** 121 * This method sets the Length value. 122 * 123 * @param[in] aLength The Length value. 124 * 125 */ SetLength(uint8_t aLength)126 void SetLength(uint8_t aLength) { mLength = aLength; } 127 128 /** 129 * This methods increases the Length value by a given amount. 130 * 131 * @param[in] aIncrement The increment amount to increase the length. 132 * 133 */ IncreaseLength(uint8_t aIncrement)134 void IncreaseLength(uint8_t aIncrement) { mLength += aIncrement; } 135 136 /** 137 * This methods decreases the Length value by a given amount. 138 * 139 * @param[in] aDecrement The decrement amount to decrease the length. 140 * 141 */ DecreaseLength(uint8_t aDecrement)142 void DecreaseLength(uint8_t aDecrement) { mLength -= aDecrement; } 143 144 /** 145 * This method returns the TLV's total size (number of bytes) including Type, Length, and Value fields. 146 * 147 * @returns The total size include Type, Length, and Value fields. 148 * 149 */ GetSize(void) const150 uint8_t GetSize(void) const { return sizeof(NetworkDataTlv) + mLength; } 151 152 /** 153 * This method returns a pointer to the Value. 154 * 155 * @returns A pointer to the value. 156 * 157 */ GetValue(void)158 uint8_t *GetValue(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(NetworkDataTlv); } 159 160 /** 161 * This method returns a pointer to the Value. 162 * 163 * @returns A pointer to the value. 164 * 165 */ GetValue(void) const166 const uint8_t *GetValue(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(NetworkDataTlv); } 167 168 /** 169 * This method returns a pointer to the next Network Data TLV. 170 * 171 * @returns A pointer to the next Network Data TLV. 172 * 173 */ GetNext(void)174 NetworkDataTlv *GetNext(void) 175 { 176 return reinterpret_cast<NetworkDataTlv *>(reinterpret_cast<uint8_t *>(this) + sizeof(*this) + mLength); 177 } 178 179 /** 180 * This method returns a pointer to the next Network Data TLV. 181 * 182 * @returns A pointer to the next Network Data TLV. 183 * 184 */ GetNext(void) const185 const NetworkDataTlv *GetNext(void) const 186 { 187 return reinterpret_cast<const NetworkDataTlv *>(reinterpret_cast<const uint8_t *>(this) + sizeof(*this) + 188 mLength); 189 } 190 191 /** 192 * This method clears the Stable bit. 193 * 194 */ ClearStable(void)195 void ClearStable(void) { mType &= ~kStableMask; } 196 197 /** 198 * This method indicates whether or not the Stable bit is set. 199 * 200 * @retval TRUE If the Stable bit is set. 201 * @retval FALSE If the Stable bit is not set. 202 * 203 */ IsStable(void) const204 bool IsStable(void) const { return (mType & kStableMask); } 205 206 /** 207 * This method sets the Stable bit. 208 * 209 */ SetStable(void)210 void SetStable(void) { mType |= kStableMask; } 211 212 /** 213 * This static method searches in a given sequence of TLVs to find the first TLV with a given type. 214 * 215 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 216 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 217 * @param[in] aType The TLV type to find. 218 * 219 * @returns A pointer to the TLV if found, or nullptr if not found. 220 * 221 */ Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,Type aType)222 static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType) 223 { 224 return const_cast<NetworkDataTlv *>( 225 Find(const_cast<const NetworkDataTlv *>(aStart), const_cast<const NetworkDataTlv *>(aEnd), aType)); 226 } 227 228 /** 229 * This static method searches in a given sequence of TLVs to find the first TLV with a given type. 230 * 231 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 232 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 233 * @param[in] aType The TLV type to find. 234 * 235 * @returns A pointer to the TLV if found, or nullptr if not found. 236 * 237 */ 238 static const NetworkDataTlv *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, Type aType); 239 240 /** 241 * This template static method searches in a given sequence of TLVs to find the first TLV with a given type. 242 * 243 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 244 * 245 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 246 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 247 * 248 * @returns A pointer to the TLV if found, or nullptr if not found. 249 * 250 */ Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd)251 template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd) 252 { 253 return static_cast<TlvType *>(Find(aStart, aEnd, TlvType::kType)); 254 } 255 256 /** 257 * This template static method searches in a given sequence of TLVs to find the first TLV with a given type. 258 * 259 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 260 * 261 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 262 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 263 * 264 * @returns A pointer to the TLV if found, or nullptr if not found. 265 * 266 */ Find(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)267 template <typename TlvType> static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd) 268 { 269 return static_cast<const TlvType *>(Find(aStart, aEnd, TlvType::kType)); 270 } 271 272 /** 273 * This static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable 274 * flag. 275 * 276 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 277 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 278 * @param[in] aType The TLV type to find. 279 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 280 * 281 * @returns A pointer to the TLV if found, or nullptr if not found. 282 * 283 */ Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,Type aType,bool aStable)284 static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType, bool aStable) 285 { 286 return const_cast<NetworkDataTlv *>( 287 Find(const_cast<const NetworkDataTlv *>(aStart), const_cast<const NetworkDataTlv *>(aEnd), aType, aStable)); 288 } 289 290 /** 291 * This static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable 292 * flag. 293 * 294 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 295 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 296 * @param[in] aType The TLV type to find. 297 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 298 * 299 * @returns A pointer to the TLV if found, or nullptr if not found. 300 * 301 */ 302 static const NetworkDataTlv *Find(const NetworkDataTlv *aStart, 303 const NetworkDataTlv *aEnd, 304 Type aType, 305 bool aStable); 306 307 /** 308 * This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and 309 * stable flag. 310 * 311 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 312 * 313 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 314 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 315 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 316 * 317 * @returns A pointer to the TLV if found, or nullptr if not found. 318 * 319 */ Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,bool aStable)320 template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable) 321 { 322 return static_cast<TlvType *>(Find(aStart, aEnd, TlvType::kType, aStable)); 323 } 324 325 /** 326 * This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and 327 * stable flag. 328 * 329 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 330 * 331 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within. 332 * @param[in] aEnd A pointer to the end of the sequence of TLVs. 333 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 334 * 335 * @returns A pointer to the TLV if found, or nullptr if not found. 336 * 337 */ 338 template <typename TlvType> Find(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd,bool aStable)339 static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, bool aStable) 340 { 341 return static_cast<const TlvType *>(Find(aStart, aEnd, TlvType::kType, aStable)); 342 } 343 344 private: 345 static constexpr uint8_t kTypeOffset = 1; 346 static constexpr uint8_t kTypeMask = 0x7f << kTypeOffset; 347 static constexpr uint8_t kStableMask = 1 << 0; 348 349 uint8_t mType; 350 uint8_t mLength; 351 } OT_TOOL_PACKED_END; 352 353 /** 354 * This class implements Has Route TLV entry generation and parsing. 355 * 356 */ 357 OT_TOOL_PACKED_BEGIN 358 class HasRouteEntry : public Equatable<HasRouteEntry> 359 { 360 friend class ExternalRouteConfig; 361 362 public: 363 /** 364 * This method initializes the header. 365 * 366 */ Init(void)367 void Init(void) 368 { 369 SetRloc(Mac::kShortAddrInvalid); 370 mFlags = 0; 371 } 372 373 /** 374 * This method returns the RLOC16 value. 375 * 376 * @returns The RLOC16 value. 377 */ GetRloc(void) const378 uint16_t GetRloc(void) const { return HostSwap16(mRloc); } 379 380 /** 381 * This method sets the RLOC16 value. 382 * 383 * @param[in] aRloc16 The RLOC16 value. 384 * 385 */ SetRloc(uint16_t aRloc16)386 void SetRloc(uint16_t aRloc16) { mRloc = HostSwap16(aRloc16); } 387 388 /** 389 * This method returns the Preference value. 390 * 391 * @returns The preference value. 392 * 393 */ GetPreference(void) const394 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); } 395 396 /** 397 * This method gets the Flags value. 398 * 399 * @returns The Flags value. 400 * 401 */ GetFlags(void) const402 uint8_t GetFlags(void) const { return mFlags; } 403 404 /** 405 * This method sets the Flags value. 406 * 407 * @param[in] aFlags The Flags value. 408 * 409 */ SetFlags(uint8_t aFlags)410 void SetFlags(uint8_t aFlags) { mFlags = aFlags; } 411 412 /** 413 * This method indicates whether or not the NAT64 flag is set. 414 * 415 * @retval TRUE If the NAT64 flag is set. 416 * @retval FALSE If the NAT64 flag is not set. 417 * 418 */ IsNat64(void) const419 bool IsNat64(void) const { return (mFlags & kNat64Flag) != 0; } 420 421 /** 422 * This method returns a pointer to the next HasRouteEntry. 423 * 424 * @returns A pointer to the next HasRouteEntry. 425 * 426 */ GetNext(void)427 HasRouteEntry *GetNext(void) { return (this + 1); } 428 429 /** 430 * This method returns a pointer to the next HasRouteEntry. 431 * 432 * @returns A pointer to the next HasRouteEntry. 433 * 434 */ GetNext(void) const435 const HasRouteEntry *GetNext(void) const { return (this + 1); } 436 437 /** 438 * This static method returns an updated flags bitmask by removing the preference bits (sets them to zero) from a 439 * given flags bitmask. 440 * 441 * @param[in] aFlags The flags bitmask. 442 * 443 * @returns An updated version @p aFlags with preference bits cleared. 444 * 445 */ FlagsWithoutPreference(uint8_t aFlags)446 static uint8_t FlagsWithoutPreference(uint8_t aFlags) { return (aFlags & ~kPreferenceMask); } 447 448 /** 449 * This static method gets the preference field from a flags bitmask. 450 * 451 * @param[in] aFlags The flags. 452 * 453 * @returns The preference field from the @p aFlags. 454 * 455 */ PreferenceFromFlags(uint8_t aFlags)456 static int8_t PreferenceFromFlags(uint8_t aFlags) { return RoutePreferenceFromValue(aFlags >> kPreferenceOffset); } 457 458 private: 459 static constexpr uint8_t kPreferenceOffset = 6; 460 static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset; 461 static constexpr uint8_t kNat64Flag = 1 << 5; 462 463 uint16_t mRloc; 464 uint8_t mFlags; 465 } OT_TOOL_PACKED_END; 466 467 /** 468 * This class implements Has Route TLV generation and parsing. 469 * 470 */ 471 OT_TOOL_PACKED_BEGIN 472 class HasRouteTlv : public NetworkDataTlv 473 { 474 public: 475 static constexpr Type kType = kTypeHasRoute; ///< The TLV Type. 476 477 /** 478 * This method initializes the TLV. 479 * 480 */ Init(void)481 void Init(void) 482 { 483 NetworkDataTlv::Init(); 484 SetType(kTypeHasRoute); 485 SetLength(0); 486 } 487 488 /** 489 * This method returns the number of HasRoute entries. 490 * 491 * @returns The number of HasRoute entries. 492 * 493 */ GetNumEntries(void) const494 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(HasRouteEntry); } 495 496 /** 497 * This method returns a pointer to the HasRoute entry at a given index. 498 * 499 * @param[in] aIndex An index. 500 * 501 * @returns A pointer to the HasRoute entry at @p aIndex. 502 * 503 */ GetEntry(uint8_t aIndex)504 HasRouteEntry *GetEntry(uint8_t aIndex) 505 { 506 return reinterpret_cast<HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry))); 507 } 508 509 /** 510 * This method returns a pointer to the HasRoute entry at a given index. 511 * 512 * @param[in] aIndex An index. 513 * 514 * @returns A pointer to the HasRoute entry at @p aIndex. 515 * 516 */ GetEntry(uint8_t aIndex) const517 const HasRouteEntry *GetEntry(uint8_t aIndex) const 518 { 519 return reinterpret_cast<const HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry))); 520 } 521 522 /** 523 * This method returns a pointer to the first HasRouteEntry (at index 0'th). 524 * 525 * @returns A pointer to the first HasRouteEntry. 526 * 527 */ GetFirstEntry(void)528 HasRouteEntry *GetFirstEntry(void) { return reinterpret_cast<HasRouteEntry *>(GetValue()); } 529 530 /** 531 * This method returns a pointer to the first HasRouteEntry (at index 0'th). 532 * 533 * @returns A pointer to the first HasRouteEntry. 534 * 535 */ GetFirstEntry(void) const536 const HasRouteEntry *GetFirstEntry(void) const { return reinterpret_cast<const HasRouteEntry *>(GetValue()); } 537 538 /** 539 * This method returns a pointer to the last HasRouteEntry. 540 * 541 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer. 542 * 543 * @returns A pointer to the last HasRouteEntry. 544 * 545 */ GetLastEntry(void)546 HasRouteEntry *GetLastEntry(void) 547 { 548 return reinterpret_cast<HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry)); 549 } 550 551 /** 552 * This method returns a pointer to the last HasRouteEntry. 553 * 554 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer. 555 * 556 * @returns A pointer to the last HasRouteEntry. 557 * 558 */ GetLastEntry(void) const559 const HasRouteEntry *GetLastEntry(void) const 560 { 561 return reinterpret_cast<const HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry)); 562 } 563 564 } OT_TOOL_PACKED_END; 565 566 /** 567 * This class implements Prefix TLV generation and parsing. 568 * 569 */ 570 OT_TOOL_PACKED_BEGIN 571 class PrefixTlv : public NetworkDataTlv 572 { 573 public: 574 static constexpr Type kType = kTypePrefix; ///< The TLV Type. 575 576 /** 577 * This method initializes the TLV. 578 * 579 * @param[in] aDomainId The Domain ID. 580 * @param[in] aPrefixLength The Prefix Length in bits. 581 * @param[in] aPrefix A pointer to the prefix. 582 * 583 */ Init(uint8_t aDomainId,uint8_t aPrefixLength,const uint8_t * aPrefix)584 void Init(uint8_t aDomainId, uint8_t aPrefixLength, const uint8_t *aPrefix) 585 { 586 NetworkDataTlv::Init(); 587 SetType(kTypePrefix); 588 mDomainId = aDomainId; 589 mPrefixLength = aPrefixLength; 590 memcpy(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)); 591 SetSubTlvsLength(0); 592 } 593 594 /** 595 * This method initializes the TLV. 596 * 597 * @param[in] aDomainId The Domain ID. 598 * @param[in] aPrefix The Prefix. 599 * 600 */ Init(uint8_t aDomainId,const Ip6::Prefix aPrefix)601 void Init(uint8_t aDomainId, const Ip6::Prefix aPrefix) 602 { 603 Init(aDomainId, aPrefix.GetLength(), aPrefix.GetBytes()); 604 } 605 606 /** 607 * This method indicates whether or not the TLV appears to be well-formed. 608 * 609 * @retval TRUE If the TLV appears to be well-formed. 610 * @retval FALSE If the TLV does not appear to be well-formed. 611 * 612 */ IsValid(void) const613 bool IsValid(void) const 614 { 615 return ((GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv)) && 616 (GetLength() >= Ip6::Prefix::SizeForLength(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv)) && 617 (Ip6::Prefix::SizeForLength(mPrefixLength) <= sizeof(Ip6::Address))); 618 } 619 620 /** 621 * This method returns the Domain ID value. 622 * 623 * @returns The Domain ID value. 624 * 625 */ GetDomainId(void) const626 uint8_t GetDomainId(void) const { return mDomainId; } 627 628 /** 629 * This method returns the Prefix Length value. 630 * 631 * @returns The Prefix Length value (in bits). 632 * 633 */ GetPrefixLength(void) const634 uint8_t GetPrefixLength(void) const { return mPrefixLength; } 635 636 /** 637 * This method returns a pointer to the Prefix. 638 * 639 * @returns A pointer to the Prefix. 640 * 641 */ GetPrefix(void)642 uint8_t *GetPrefix(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); } 643 644 /** 645 * This method returns a pointer to the Prefix. 646 * 647 * @returns A pointer to the Prefix. 648 * 649 */ GetPrefix(void) const650 const uint8_t *GetPrefix(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); } 651 652 /** 653 * This method copies the Prefix from TLV into a given `Ip6::Prefix`. 654 * 655 * @param[out] aPrefix An `Ip6::Prefix` to copy the Prefix from TLV into. 656 * 657 */ CopyPrefixTo(Ip6::Prefix & aPrefix) const658 void CopyPrefixTo(Ip6::Prefix &aPrefix) const { aPrefix.Set(GetPrefix(), GetPrefixLength()); } 659 660 /** 661 * This method indicates whether the Prefix from TLV is equal to a given `Ip6::Prefix`. 662 * 663 * @param[in] aPrefix A Prefix to compare with. 664 * 665 * @retval TRUE The TLV's Prefix is equal to @p aPrefix. 666 * @retval FALSE The TLV's Prefix is not equal to @p aPrefix. 667 * 668 */ IsEqual(Ip6::Prefix & aPrefix) const669 bool IsEqual(Ip6::Prefix &aPrefix) const { return aPrefix.IsEqual(GetPrefix(), GetPrefixLength()); } 670 671 /** 672 * This method indicates whether the Prefix from TLV is equal to a given Prefix. 673 * 674 * @param[in] aPrefix A pointer to an IPv6 prefix to compare with. 675 * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits). 676 * 677 * @retval TRUE The TLV's Prefix is equal to @p aPrefix. 678 * @retval FALSE The TLV's Prefix is not equal @p aPrefix. 679 * 680 */ IsEqual(const uint8_t * aPrefix,uint8_t aPrefixLength) const681 bool IsEqual(const uint8_t *aPrefix, uint8_t aPrefixLength) const 682 { 683 return (aPrefixLength == mPrefixLength) && 684 (Ip6::Prefix::MatchLength(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)) >= 685 mPrefixLength); 686 } 687 688 /** 689 * This method returns a pointer to the Sub-TLVs. 690 * 691 * @returns A pointer to the Sub-TLVs. 692 * 693 */ GetSubTlvs(void)694 NetworkDataTlv *GetSubTlvs(void) 695 { 696 return reinterpret_cast<NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength)); 697 } 698 699 /** 700 * This method returns a pointer to the Sub-TLVs. 701 * 702 * @returns A pointer to the Sub-TLVs. 703 * 704 */ GetSubTlvs(void) const705 const NetworkDataTlv *GetSubTlvs(void) const 706 { 707 return reinterpret_cast<const NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength)); 708 } 709 710 /** 711 * This method returns the Sub-TLVs length in bytes. 712 * 713 * @returns The Sub-TLVs length in bytes. 714 * 715 */ GetSubTlvsLength(void) const716 uint8_t GetSubTlvsLength(void) const 717 { 718 return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength)); 719 } 720 721 /** 722 * This method sets the Sub-TLVs length in bytes. 723 * 724 * @param[in] aLength The Sub-TLVs length in bytes. 725 * 726 */ SetSubTlvsLength(uint8_t aLength)727 void SetSubTlvsLength(uint8_t aLength) 728 { 729 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength) + aLength); 730 } 731 732 /** 733 * This template method searches in the sub-TLVs to find the first one matching a given TLV type. 734 * 735 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 736 * 737 * @returns A pointer to the TLV if found, or nullptr if not found. 738 * 739 */ FindSubTlv(void)740 template <typename SubTlvType> SubTlvType *FindSubTlv(void) 741 { 742 return static_cast<SubTlvType *>(FindSubTlv(SubTlvType::kType)); 743 } 744 745 /** 746 * This template method searches in the sub-TLVs to find the first one matching a given TLV Type. 747 * 748 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 749 * 750 * @returns A pointer to the TLV if found, or nullptr if not found. 751 * 752 */ FindSubTlv(void) const753 template <typename SubTlvType> const SubTlvType *FindSubTlv(void) const 754 { 755 return static_cast<const SubTlvType *>(FindSubTlv(SubTlvType::kType)); 756 } 757 758 /** 759 * This template method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag. 760 * 761 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 762 * 763 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 764 * 765 * @returns A pointer to the TLV if found, or nullptr if not found. 766 * 767 */ FindSubTlv(bool aStable)768 template <typename SubTlvType> SubTlvType *FindSubTlv(bool aStable) 769 { 770 return static_cast<SubTlvType *>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable)); 771 } 772 773 /** 774 * This template method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag. 775 * 776 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`). 777 * 778 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 779 * 780 * @returns A pointer to the TLV if found, or nullptr if not found. 781 * 782 */ FindSubTlv(bool aStable) const783 template <typename SubTlvType> const SubTlvType *FindSubTlv(bool aStable) const 784 { 785 return static_cast<const SubTlvType *>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable)); 786 } 787 788 /** 789 * This method searches in the sub-TLVs to find the first one matching a given TLV type. 790 * 791 * @param[in] aType The sub-TLV type to search for. 792 * 793 * @returns A pointer to the TLV if found, or nullptr if not found. 794 * 795 */ FindSubTlv(Type aType)796 NetworkDataTlv *FindSubTlv(Type aType) 797 { 798 return const_cast<NetworkDataTlv *>(const_cast<const PrefixTlv *>(this)->FindSubTlv(aType)); 799 } 800 801 /** 802 * This method searches in the sub-TLVs to find the first one matching a given TLV type. 803 * 804 * @param[in] aType The sub-TLV type to search for. 805 * 806 * @returns A pointer to the TLV if found, or nullptr if not found. 807 * 808 */ 809 const NetworkDataTlv *FindSubTlv(Type aType) const; 810 811 /** 812 * This method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag. 813 * 814 * @param[in] aType The sub-TLV type to search for. 815 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 816 * 817 * @returns A pointer to the TLV if found, or nullptr if not found. 818 * 819 */ FindSubTlv(Type aType,bool aStable)820 NetworkDataTlv *FindSubTlv(Type aType, bool aStable) 821 { 822 return const_cast<NetworkDataTlv *>(const_cast<const PrefixTlv *>(this)->FindSubTlv(aType, aStable)); 823 } 824 825 /** 826 * This method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag. 827 * 828 * @param[in] aType The sub-TLV type to search for. 829 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 830 * 831 * @returns A pointer to the TLV if found, or nullptr if not found. 832 * 833 */ 834 const NetworkDataTlv *FindSubTlv(Type aType, bool aStable) const; 835 836 /** 837 * This static method calculates the total size (number of bytes) of a Prefix TLV with a given Prefix Length value. 838 * 839 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any 840 * sub TLVs of the Prefix TLV. 841 * 842 * @param[in] aPrefixLength A Prefix Length in bits. 843 844 * @returns The size (number of bytes) of the Prefix TLV. 845 * 846 */ CalculateSize(uint8_t aPrefixLength)847 static uint16_t CalculateSize(uint8_t aPrefixLength) 848 { 849 return sizeof(PrefixTlv) + Ip6::Prefix::SizeForLength(aPrefixLength); 850 } 851 852 private: 853 uint8_t mDomainId; 854 uint8_t mPrefixLength; 855 } OT_TOOL_PACKED_END; 856 857 /** 858 * This class implements Border Router Entry generation and parsing. 859 * 860 */ 861 OT_TOOL_PACKED_BEGIN 862 class BorderRouterEntry : public Equatable<BorderRouterEntry> 863 { 864 friend class OnMeshPrefixConfig; 865 866 public: 867 /** 868 * This method initializes the TLV. 869 * 870 */ Init(void)871 void Init(void) 872 { 873 SetRloc(Mac::kShortAddrInvalid); 874 mFlags = 0; 875 } 876 877 /** 878 * This method returns the RLOC16 value. 879 * 880 * @returns The RLOC16 value. 881 */ GetRloc(void) const882 uint16_t GetRloc(void) const { return HostSwap16(mRloc); } 883 884 /** 885 * This method sets the RLOC16 value. 886 * 887 * @param[in] aRloc16 The RLOC16 value. 888 * 889 */ SetRloc(uint16_t aRloc16)890 void SetRloc(uint16_t aRloc16) { mRloc = HostSwap16(aRloc16); } 891 892 /** 893 * This method returns the Flags value. 894 * 895 * @returns The Flags value. 896 * 897 */ GetFlags(void) const898 uint16_t GetFlags(void) const { return HostSwap16(mFlags); } 899 900 /** 901 * This method sets the Flags value. 902 * 903 * @param[in] aFlags The Flags value. 904 * 905 */ SetFlags(uint16_t aFlags)906 void SetFlags(uint16_t aFlags) { mFlags = HostSwap16(aFlags); } 907 908 /** 909 * This method returns the Preference value. 910 * 911 * @returns the Preference value. 912 * 913 */ GetPreference(void) const914 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); } 915 916 /** 917 * This method indicates whether or not the Preferred flag is set. 918 * 919 * @retval TRUE If the Preferred flag is set. 920 * @retval FALSE If the Preferred flag is not set. 921 * 922 */ IsPreferred(void) const923 bool IsPreferred(void) const { return (HostSwap16(mFlags) & kPreferredFlag) != 0; } 924 925 /** 926 * This method indicates whether or not the SLAAC flag is set. 927 * 928 * @retval TRUE If the SLAAC flag is set. 929 * @retval FALSE If the SLAAC flag is not set. 930 * 931 */ IsSlaac(void) const932 bool IsSlaac(void) const { return (HostSwap16(mFlags) & kSlaacFlag) != 0; } 933 934 /** 935 * This method indicates whether or not the DHCP flag is set. 936 * 937 * @retval TRUE If the DHCP flag is set. 938 * @retval FALSE If the DHCP flag is not set. 939 * 940 */ IsDhcp(void) const941 bool IsDhcp(void) const { return (HostSwap16(mFlags) & kDhcpFlag) != 0; } 942 943 /** 944 * This method indicates whether or not the Configure flag is set. 945 * 946 * @retval TRUE If the Configure flag is set. 947 * @retval FALSE If the Configure flag is not set. 948 * 949 */ IsConfigure(void) const950 bool IsConfigure(void) const { return (HostSwap16(mFlags) & kConfigureFlag) != 0; } 951 952 /** 953 * This method indicates whether or not the Default Route flag is set. 954 * 955 * @retval TRUE If the Default Route flag is set. 956 * @retval FALSE If the Default Route flag is not set. 957 * 958 */ IsDefaultRoute(void) const959 bool IsDefaultRoute(void) const { return (HostSwap16(mFlags) & kDefaultRouteFlag) != 0; } 960 961 /** 962 * This method indicates whether or not the On-Mesh flag is set. 963 * 964 * @retval TRUE If the On-Mesh flag is set. 965 * @retval FALSE If the On-Mesh flag is not set. 966 * 967 */ IsOnMesh(void) const968 bool IsOnMesh(void) const { return (HostSwap16(mFlags) & kOnMeshFlag) != 0; } 969 970 /** 971 * This method indicates whether or not the Nd-Dns flag is set. 972 * 973 * @retval TRUE If the Nd-Dns flag is set. 974 * @retval FALSE If the Nd-Dns flag is not set. 975 * 976 */ IsNdDns(void) const977 bool IsNdDns(void) const { return (HostSwap16(mFlags) & kNdDnsFlag) != 0; } 978 979 /** 980 * This method indicates whether or not the Domain Prefix flag is set. 981 * 982 * @retval TRUE If the Domain Prefix flag is set. 983 * @retval FALSE If the Domain Prefix flag is not set. 984 * 985 */ IsDp(void) const986 bool IsDp(void) const { return (HostSwap16(mFlags) & kDpFlag) != 0; } 987 988 /** 989 * This method returns a pointer to the next BorderRouterEntry 990 * 991 * @returns A pointer to the next BorderRouterEntry. 992 * 993 */ GetNext(void)994 BorderRouterEntry *GetNext(void) { return (this + 1); } 995 996 /** 997 * This method returns a pointer to the next BorderRouterEntry 998 * 999 * @returns A pointer to the next BorderRouterEntry. 1000 * 1001 */ GetNext(void) const1002 const BorderRouterEntry *GetNext(void) const { return (this + 1); } 1003 1004 /** 1005 * This static method returns an updated flags bitmask by removing the preference bits (sets them to zero) from a 1006 * given flags bitmask. 1007 * 1008 * @param[in] aFlags The flags bitmask. 1009 * 1010 * @returns An updated version @p aFlags with preference bits cleared. 1011 * 1012 */ FlagsWithoutPreference(uint16_t aFlags)1013 static uint16_t FlagsWithoutPreference(uint16_t aFlags) { return (aFlags & ~kPreferenceMask); } 1014 1015 /** 1016 * This static method gets the preference field from a flags bitmask. 1017 * 1018 * @param[in] aFlags The flags. 1019 * 1020 * @returns The preference field from the @p aFlags. 1021 * 1022 */ PreferenceFromFlags(uint16_t aFlags)1023 static int8_t PreferenceFromFlags(uint16_t aFlags) 1024 { 1025 return RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> kPreferenceOffset)); 1026 } 1027 1028 private: 1029 static constexpr uint8_t kPreferenceOffset = 14; 1030 static constexpr uint16_t kPreferenceMask = 3 << kPreferenceOffset; 1031 static constexpr uint16_t kPreferredFlag = 1 << 13; 1032 static constexpr uint16_t kSlaacFlag = 1 << 12; 1033 static constexpr uint16_t kDhcpFlag = 1 << 11; 1034 static constexpr uint16_t kConfigureFlag = 1 << 10; 1035 static constexpr uint16_t kDefaultRouteFlag = 1 << 9; 1036 static constexpr uint16_t kOnMeshFlag = 1 << 8; 1037 static constexpr uint16_t kNdDnsFlag = 1 << 7; 1038 static constexpr uint16_t kDpFlag = 1 << 6; 1039 1040 uint16_t mRloc; 1041 uint16_t mFlags; 1042 } OT_TOOL_PACKED_END; 1043 1044 /** 1045 * This class implements Border Router TLV generation and parsing. 1046 * 1047 */ 1048 OT_TOOL_PACKED_BEGIN 1049 class BorderRouterTlv : public NetworkDataTlv 1050 { 1051 public: 1052 static constexpr Type kType = kTypeBorderRouter; ///< The TLV Type. 1053 1054 /** 1055 * This method initializes the TLV. 1056 * 1057 */ Init(void)1058 void Init(void) 1059 { 1060 NetworkDataTlv::Init(); 1061 SetType(kTypeBorderRouter); 1062 SetLength(0); 1063 } 1064 1065 /** 1066 * This method returns the number of Border Router entries. 1067 * 1068 * @returns The number of Border Router entries. 1069 * 1070 */ GetNumEntries(void) const1071 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(BorderRouterEntry); } 1072 1073 /** 1074 * This method returns a pointer to the Border Router entry at a given index 1075 * 1076 * @param[in] aIndex The index. 1077 * 1078 * @returns A pointer to the Border Router entry at @p aIndex. 1079 * 1080 */ GetEntry(uint8_t aIndex)1081 BorderRouterEntry *GetEntry(uint8_t aIndex) 1082 { 1083 return reinterpret_cast<BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry))); 1084 } 1085 1086 /** 1087 * This method returns a pointer to the Border Router entry at a given index. 1088 * 1089 * @param[in] aIndex The index. 1090 * 1091 * @returns A pointer to the Border Router entry at @p aIndex 1092 * 1093 */ GetEntry(uint8_t aIndex) const1094 const BorderRouterEntry *GetEntry(uint8_t aIndex) const 1095 { 1096 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry))); 1097 } 1098 1099 /** 1100 * This method returns a pointer to the first BorderRouterEntry (at index 0'th). 1101 * 1102 * @returns A pointer to the first BorderRouterEntry. 1103 * 1104 */ GetFirstEntry(void)1105 BorderRouterEntry *GetFirstEntry(void) { return reinterpret_cast<BorderRouterEntry *>(GetValue()); } 1106 1107 /** 1108 * This method returns a pointer to the first BorderRouterEntry (at index 0'th). 1109 * 1110 * @returns A pointer to the first BorderRouterEntry. 1111 * 1112 */ GetFirstEntry(void) const1113 const BorderRouterEntry *GetFirstEntry(void) const 1114 { 1115 return reinterpret_cast<const BorderRouterEntry *>(GetValue()); 1116 } 1117 1118 /** 1119 * This method returns a pointer to the last BorderRouterEntry. 1120 * 1121 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer. 1122 * 1123 * @returns A pointer to the last BorderRouterEntry. 1124 * 1125 */ GetLastEntry(void)1126 BorderRouterEntry *GetLastEntry(void) 1127 { 1128 return reinterpret_cast<BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry)); 1129 } 1130 1131 /** 1132 * This method returns a pointer to the last BorderRouterEntry. 1133 * 1134 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer. 1135 * 1136 * @returns A pointer to the last BorderRouterEntry. 1137 * 1138 */ GetLastEntry(void) const1139 const BorderRouterEntry *GetLastEntry(void) const 1140 { 1141 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry)); 1142 } 1143 1144 } OT_TOOL_PACKED_END; 1145 1146 /** 1147 * This class implements Context TLV generation and processing. 1148 * 1149 */ 1150 OT_TOOL_PACKED_BEGIN 1151 class ContextTlv : public NetworkDataTlv 1152 { 1153 public: 1154 static constexpr Type kType = kTypeContext; ///< The TLV Type. 1155 1156 /** 1157 * This method initializes the Context TLV. 1158 * 1159 * @param[in] aConextId The Context ID value. 1160 * @param[in] aLength The Context Length value. 1161 * 1162 */ Init(uint8_t aContextId,uint8_t aConextLength)1163 void Init(uint8_t aContextId, uint8_t aConextLength) 1164 { 1165 NetworkDataTlv::Init(); 1166 SetType(kTypeContext); 1167 SetLength(sizeof(ContextTlv) - sizeof(NetworkDataTlv)); 1168 mFlags = ((aContextId << kContextIdOffset) & kContextIdMask); 1169 mContextLength = aConextLength; 1170 } 1171 1172 /** 1173 * This method indicates whether or not the Compress flag is set. 1174 * 1175 * @retval TRUE The Compress flag is set. 1176 * @retval FALSE The Compress flags is not set. 1177 * 1178 */ IsCompress(void) const1179 bool IsCompress(void) const { return (mFlags & kCompressFlag) != 0; } 1180 1181 /** 1182 * This method clears the Compress flag. 1183 * 1184 */ ClearCompress(void)1185 void ClearCompress(void) { mFlags &= ~kCompressFlag; } 1186 1187 /** 1188 * This method sets the Compress flag. 1189 * 1190 */ SetCompress(void)1191 void SetCompress(void) { mFlags |= kCompressFlag; } 1192 1193 /** 1194 * This method returns the Context ID value. 1195 * 1196 * @returns The Context ID value. 1197 * 1198 */ GetContextId(void) const1199 uint8_t GetContextId(void) const { return mFlags & kContextIdMask; } 1200 1201 /** 1202 * This method returns the Context Length value. 1203 * 1204 * @returns The Context Length value. 1205 * 1206 */ GetContextLength(void) const1207 uint8_t GetContextLength(void) const { return mContextLength; } 1208 1209 private: 1210 static constexpr uint8_t kCompressFlag = 1 << 4; 1211 static constexpr uint8_t kContextIdOffset = 0; 1212 static constexpr uint8_t kContextIdMask = 0xf << kContextIdOffset; 1213 1214 uint8_t mFlags; 1215 uint8_t mContextLength; 1216 } OT_TOOL_PACKED_END; 1217 1218 /** 1219 * This class implements Commissioning Data TLV generation and parsing. 1220 * 1221 */ 1222 OT_TOOL_PACKED_BEGIN 1223 class CommissioningDataTlv : public NetworkDataTlv 1224 { 1225 public: 1226 static constexpr Type kType = kTypeCommissioningData; ///< The TLV Type. 1227 1228 /** 1229 * This method initializes the TLV. 1230 * 1231 */ Init(void)1232 void Init(void) 1233 { 1234 NetworkDataTlv::Init(); 1235 SetType(kTypeCommissioningData); 1236 SetLength(0); 1237 } 1238 } OT_TOOL_PACKED_END; 1239 1240 /** 1241 * This class implements Service Data TLV generation and parsing. 1242 * 1243 */ 1244 OT_TOOL_PACKED_BEGIN 1245 class ServiceTlv : public NetworkDataTlv 1246 { 1247 public: 1248 static constexpr Type kType = kTypeService; ///< The TLV Type. 1249 1250 static constexpr uint32_t kThreadEnterpriseNumber = 44970; ///< Thread enterprise number. 1251 1252 /** 1253 * This method initializes the TLV. 1254 * 1255 * @param[in] aServiceId The Service Id value. 1256 * @param[in] aEnterpriseNumber The Enterprise Number. 1257 * @param[in] aServiceData The Service Data. 1258 * @param[in] aServiceDataLength The Service Data length (number of bytes). 1259 * 1260 */ Init(uint8_t aServiceId,uint32_t aEnterpriseNumber,const uint8_t * aServiceData,uint8_t aServiceDataLength)1261 void Init(uint8_t aServiceId, uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength) 1262 { 1263 NetworkDataTlv::Init(); 1264 SetType(kTypeService); 1265 1266 mFlagsServiceId = (aEnterpriseNumber == kThreadEnterpriseNumber) ? kThreadEnterpriseFlag : 0; 1267 mFlagsServiceId |= (aServiceId & kServiceIdMask); 1268 1269 if (aEnterpriseNumber != kThreadEnterpriseNumber) 1270 { 1271 mShared.mEnterpriseNumber = HostSwap32(aEnterpriseNumber); 1272 mServiceDataLength = aServiceDataLength; 1273 memcpy(&mServiceDataLength + sizeof(uint8_t), aServiceData, aServiceDataLength); 1274 } 1275 else 1276 { 1277 mShared.mServiceDataLengthThreadEnterprise = aServiceDataLength; 1278 memcpy(&mShared.mServiceDataLengthThreadEnterprise + sizeof(uint8_t), aServiceData, aServiceDataLength); 1279 } 1280 1281 SetLength(GetFieldsLength()); 1282 } 1283 1284 /** 1285 * This method indicates whether or not the TLV appears to be well-formed. 1286 * 1287 * @retval TRUE If the TLV appears to be well-formed. 1288 * @retval FALSE If the TLV does not appear to be well-formed. 1289 * 1290 */ IsValid(void) const1291 bool IsValid(void) const 1292 { 1293 uint8_t length = GetLength(); 1294 1295 return (length >= sizeof(mFlagsServiceId)) && 1296 (length >= kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t))) && 1297 (static_cast<uint16_t>(length) + sizeof(NetworkDataTlv) >= 1298 CalculateSize(GetEnterpriseNumber(), GetServiceDataLength())); 1299 } 1300 1301 /** 1302 * This method returns the Service ID. It is in range 0x00-0x0f. 1303 * 1304 * @returns the Service ID. 1305 * 1306 */ GetServiceId(void) const1307 uint8_t GetServiceId(void) const { return (mFlagsServiceId & kServiceIdMask); } 1308 1309 /** 1310 * This method returns Enterprise Number field. 1311 * 1312 * @returns The Enterprise Number. 1313 * 1314 */ GetEnterpriseNumber(void) const1315 uint32_t GetEnterpriseNumber(void) const 1316 { 1317 return IsThreadEnterprise() ? static_cast<uint32_t>(kThreadEnterpriseNumber) 1318 : HostSwap32(mShared.mEnterpriseNumber); 1319 } 1320 1321 /** 1322 * This method gets Service Data length. 1323 * 1324 * @returns length of the Service Data field in bytes. 1325 * 1326 */ GetServiceDataLength(void) const1327 uint8_t GetServiceDataLength(void) const 1328 { 1329 return IsThreadEnterprise() ? mShared.mServiceDataLengthThreadEnterprise : mServiceDataLength; 1330 } 1331 1332 /** 1333 * This method returns a pointer to the Service Data. 1334 * 1335 * @returns A pointer to the Service Data. 1336 * 1337 */ GetServiceData(void)1338 uint8_t *GetServiceData(void) 1339 { 1340 return (IsThreadEnterprise() ? &mShared.mServiceDataLengthThreadEnterprise : &mServiceDataLength) + 1341 sizeof(uint8_t); 1342 } 1343 1344 /** 1345 * This method returns a pointer to the Service Data. 1346 * 1347 * @returns A pointer to the Service Data. 1348 * 1349 */ GetServiceData(void) const1350 const uint8_t *GetServiceData(void) const 1351 { 1352 return (IsThreadEnterprise() ? &mShared.mServiceDataLengthThreadEnterprise : &mServiceDataLength) + 1353 sizeof(uint8_t); 1354 } 1355 1356 /** 1357 * This method returns the Sub-TLVs length in bytes. 1358 * 1359 * @returns The Sub-TLVs length in bytes. 1360 * 1361 */ GetSubTlvsLength(void)1362 uint8_t GetSubTlvsLength(void) { return GetLength() - GetFieldsLength(); } 1363 1364 /** 1365 * This method sets the Sub-TLVs length in bytes. 1366 * 1367 * @param[in] aLength The Sub-TLVs length in bytes. 1368 * 1369 */ SetSubTlvsLength(uint8_t aLength)1370 void SetSubTlvsLength(uint8_t aLength) { SetLength(GetFieldsLength() + aLength); } 1371 1372 /** 1373 * This method returns a pointer to the Sub-TLVs. 1374 * 1375 * @returns A pointer to the Sub-TLVs. 1376 * 1377 */ GetSubTlvs(void)1378 NetworkDataTlv *GetSubTlvs(void) { return reinterpret_cast<NetworkDataTlv *>(GetValue() + GetFieldsLength()); } 1379 1380 /** 1381 * This method returns a pointer to the Sub-TLVs. 1382 * 1383 * @returns A pointer to the Sub-TLVs. 1384 * 1385 */ GetSubTlvs(void) const1386 const NetworkDataTlv *GetSubTlvs(void) const 1387 { 1388 return reinterpret_cast<const NetworkDataTlv *>(GetValue() + GetFieldsLength()); 1389 } 1390 1391 /** 1392 * This static method calculates the total size (number of bytes) of a Service TLV with a given Enterprise Number 1393 * and Service Data length. 1394 * 1395 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any 1396 * sub-TLVs of the Service TLV. 1397 * 1398 * @param[in] aEnterpriseNumber A Enterprise Number. 1399 * @param[in] aServiceDataLength A Service Data length. 1400 * 1401 * @returns The size (number of bytes) of the Service TLV. 1402 * 1403 */ CalculateSize(uint32_t aEnterpriseNumber,uint8_t aServiceDataLength)1404 static uint16_t CalculateSize(uint32_t aEnterpriseNumber, uint8_t aServiceDataLength) 1405 { 1406 return sizeof(NetworkDataTlv) + kMinLength + aServiceDataLength + 1407 ((aEnterpriseNumber == kThreadEnterpriseNumber) ? 0 : sizeof(uint32_t) /* mEnterpriseNumber */); 1408 } 1409 1410 private: IsThreadEnterprise(void) const1411 bool IsThreadEnterprise(void) const { return (mFlagsServiceId & kThreadEnterpriseFlag) != 0; } 1412 GetFieldsLength(void) const1413 uint8_t GetFieldsLength(void) const 1414 { 1415 // Returns the length of TLV value's common fields (flags, enterprise 1416 // number and service data) excluding any sub-TLVs. 1417 1418 return kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t)) + GetServiceDataLength(); 1419 } 1420 1421 static constexpr uint8_t kThreadEnterpriseFlag = (1 << 7); 1422 static constexpr uint8_t kServiceIdMask = 0xf; 1423 static constexpr uint8_t kMinLength = sizeof(uint8_t) + sizeof(uint8_t); // Flags & Service Data length. 1424 1425 // When `kThreadEnterpriseFlag is set in the `mFlagsServiceId`, the 1426 // `mEnterpriseNumber` field is elided and `mFlagsServiceId` is 1427 // immediately followed by the Service Data length field (which is 1428 // represented by `mServiceDataLengthThreadEnterprise`) 1429 1430 uint8_t mFlagsServiceId; 1431 union OT_TOOL_PACKED_FIELD 1432 { 1433 uint32_t mEnterpriseNumber; 1434 uint8_t mServiceDataLengthThreadEnterprise; 1435 } mShared; 1436 uint8_t mServiceDataLength; 1437 1438 } OT_TOOL_PACKED_END; 1439 1440 /** 1441 * This class implements Server Data TLV generation and parsing. 1442 * 1443 */ 1444 OT_TOOL_PACKED_BEGIN 1445 class ServerTlv : public NetworkDataTlv 1446 { 1447 public: 1448 static constexpr Type kType = kTypeServer; ///< The TLV Type. 1449 1450 /** 1451 * This method initializes the Server TLV. 1452 * 1453 * @param[in] aServer16 The Server16 value. 1454 * @param[in] aServerData The Server Data. 1455 * @param[in] aServerDataLength Server Data length in bytes. 1456 * 1457 */ Init(uint16_t aServer16,const uint8_t * aServerData,uint8_t aServerDataLength)1458 void Init(uint16_t aServer16, const uint8_t *aServerData, uint8_t aServerDataLength) 1459 { 1460 NetworkDataTlv::Init(); 1461 SetType(kTypeServer); 1462 SetServer16(aServer16); 1463 memcpy(reinterpret_cast<uint8_t *>(this) + sizeof(*this), aServerData, aServerDataLength); 1464 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + aServerDataLength); 1465 } 1466 1467 /** 1468 * This method indicates whether or not the TLV appears to be well-formed. 1469 * 1470 * @retval TRUE If the TLV appears to be well-formed. 1471 * @retval FALSE If the TLV does not appear to be well-formed. 1472 * 1473 */ IsValid(void) const1474 bool IsValid(void) const { return GetLength() >= (sizeof(*this) - sizeof(NetworkDataTlv)); } 1475 1476 /** 1477 * This method returns the Server16 value. 1478 * 1479 * @returns The Server16 value. 1480 * 1481 */ GetServer16(void) const1482 uint16_t GetServer16(void) const { return HostSwap16(mServer16); } 1483 1484 /* 1485 * This method sets the Server16 value. 1486 * 1487 * @param[in] aServer16 The Server16 value. 1488 * 1489 */ SetServer16(uint16_t aServer16)1490 void SetServer16(uint16_t aServer16) { mServer16 = HostSwap16(aServer16); } 1491 1492 /** 1493 * This method returns the Server Data. 1494 * 1495 * @returns A pointer to the Server Data. 1496 * 1497 */ GetServerData(void) const1498 const uint8_t *GetServerData(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); } 1499 1500 /** 1501 * This method returns the Server Data length in bytes. 1502 * 1503 * @returns The Server Data length in bytes. 1504 * 1505 */ GetServerDataLength(void) const1506 uint8_t GetServerDataLength(void) const { return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv)); } 1507 1508 /** 1509 * This method indicates whether two Server TLVs fully match. 1510 * 1511 * @param[in] aOther Another Server TLV to compare with it. 1512 * 1513 * @retval TRUE The two TLVs are equal. 1514 * @retval FALSE The two TLVs are not equal. 1515 * 1516 */ operator ==(const ServerTlv & aOther) const1517 bool operator==(const ServerTlv &aOther) const 1518 { 1519 return (GetLength() == aOther.GetLength()) && (memcmp(GetValue(), aOther.GetValue(), GetLength()) == 0); 1520 } 1521 1522 /** 1523 * This static method calculates the total size (number of bytes) of a Service TLV with a given Server Data length. 1524 * 1525 * Note that the returned size does include the Type and Length fields in the TLV. 1526 * 1527 * @param[in] aServerDataLength Server Data length in bytes. 1528 * 1529 * @returns The size (number of bytes) of the Server TLV. 1530 * 1531 */ CalculateSize(uint8_t aServerDataLength)1532 static uint16_t CalculateSize(uint8_t aServerDataLength) { return sizeof(ServerTlv) + aServerDataLength; } 1533 1534 private: 1535 uint16_t mServer16; 1536 } OT_TOOL_PACKED_END; 1537 1538 /** 1539 * This class represents a Network Data TLV iterator. 1540 * 1541 */ 1542 class TlvIterator 1543 { 1544 public: 1545 /** 1546 * This constructor initializes the `TlvIterator` to iterate over a given sequence of TLVs. 1547 * 1548 * @param[in] aStart A pointer to the start of the TLV sequence. 1549 * @param[in] aEnd A pointer to the end of the TLV sequence. 1550 * 1551 */ TlvIterator(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)1552 TlvIterator(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd) 1553 : mStart(aStart) 1554 , mEnd(aEnd) 1555 { 1556 } 1557 1558 /** 1559 * This constructor initializes the `TlvIterator` to iterate over TLVs from a given buffer. 1560 * 1561 * @param[in] aBuffer A pointer to a buffer containing the TLVs. 1562 * @param[in] aLength The length (number of bytes) of @p aBuffer. 1563 * 1564 */ TlvIterator(const uint8_t * aBuffer,uint8_t aLength)1565 TlvIterator(const uint8_t *aBuffer, uint8_t aLength) 1566 : TlvIterator(reinterpret_cast<const NetworkDataTlv *>(aBuffer), 1567 reinterpret_cast<const NetworkDataTlv *>(aBuffer + aLength)) 1568 { 1569 } 1570 1571 /** 1572 * This constructor initializes the `TlvIterator` to iterate over sub-TLVs of a given Prefix TLV. 1573 * 1574 * @param[in] aPrefixTlv A Prefix TLV to iterate over its sub-TLVs. 1575 * 1576 */ TlvIterator(const PrefixTlv & aPrefixTlv)1577 explicit TlvIterator(const PrefixTlv &aPrefixTlv) 1578 : TlvIterator(aPrefixTlv.GetSubTlvs(), aPrefixTlv.GetNext()) 1579 { 1580 } 1581 1582 /** 1583 * This constructor initializes the `TlvIterator` to iterate over sub-TLVs of a given Service TLV. 1584 * 1585 * @param[in] aServiceTlv A Service TLV to iterate over its sub-TLVs. 1586 * 1587 */ TlvIterator(const ServiceTlv & aServiceTlv)1588 explicit TlvIterator(const ServiceTlv &aServiceTlv) 1589 : TlvIterator(aServiceTlv.GetSubTlvs(), aServiceTlv.GetNext()) 1590 { 1591 } 1592 1593 /** 1594 * This template method iterates to the next TLV with a given type. 1595 * 1596 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`). 1597 * 1598 * @returns A pointer to the next TLV, or nullptr if it can not be found. 1599 * 1600 */ Iterate(void)1601 template <typename TlvType> const TlvType *Iterate(void) 1602 { 1603 return static_cast<const TlvType *>(Iterate(TlvType::kType)); 1604 } 1605 1606 /** 1607 * This template method iterates to the next TLV with a given type and stable flag. 1608 * 1609 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`). 1610 * 1611 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable. 1612 * 1613 * @returns A pointer to the next TLV, or nullptr if it can not be found. 1614 * 1615 */ Iterate(bool aStable)1616 template <typename TlvType> const TlvType *Iterate(bool aStable) 1617 { 1618 return static_cast<const TlvType *>(Iterate(TlvType::kType, aStable)); 1619 } 1620 1621 private: 1622 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType); 1623 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType, bool aStable); 1624 1625 const NetworkDataTlv *mStart; 1626 const NetworkDataTlv *mEnd; 1627 }; 1628 1629 /** 1630 * @} 1631 * 1632 */ 1633 1634 } // namespace NetworkData 1635 } // namespace ot 1636 1637 #endif // NETWORK_DATA_TLVS_HPP_ 1638