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