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