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