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