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