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