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