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 managing MeshCoP Datasets.
32  *
33  */
34 
35 #ifndef MESHCOP_DATASET_HPP_
36 #define MESHCOP_DATASET_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include <openthread/dataset.h>
41 
42 #include "common/as_core_type.hpp"
43 #include "common/clearable.hpp"
44 #include "common/const_cast.hpp"
45 #include "common/locator.hpp"
46 #include "common/message.hpp"
47 #include "common/timer.hpp"
48 #include "common/type_traits.hpp"
49 #include "meshcop/meshcop_tlvs.hpp"
50 #include "thread/mle_types.hpp"
51 
52 namespace ot {
53 namespace MeshCoP {
54 
55 /**
56  * Represents MeshCop Dataset.
57  *
58  */
59 class Dataset
60 {
61     friend class DatasetManager;
62 
63 public:
64     static constexpr uint8_t kMaxLength = OT_OPERATIONAL_DATASET_MAX_LENGTH; ///< Max length of Dataset (bytes)
65 
66     /**
67      * Represents the Dataset type (active or pending).
68      *
69      */
70     enum Type : uint8_t
71     {
72         kActive,  ///< Active Dataset
73         kPending, ///< Pending Dataset
74     };
75 
76     /**
77      * Represents a Dataset as a sequence of TLVs.
78      *
79      */
80     typedef otOperationalDatasetTlvs Tlvs;
81 
82     /**
83      * Represents a component in Dataset.
84      *
85      */
86     enum Component : uint8_t
87     {
88         kActiveTimestamp,  ///< Active Timestamp
89         kPendingTimestamp, ///< Pending Timestamp
90         kNetworkKey,       ///< Network Key
91         kNetworkName,      ///< Network Name
92         kExtendedPanId,    ///< Extended PAN Identifier
93         kMeshLocalPrefix,  ///< Mesh Local Prefix
94         kDelay,            ///< Delay
95         kPanId,            ///< PAN Identifier
96         kChannel,          ///< Channel
97         kPskc,             ///< PSKc
98         kSecurityPolicy,   ///< Security Policy
99         kChannelMask,      ///< Channel Mask
100     };
101 
102     template <Component kComponent> struct TypeFor; ///< Specifies the associate type for a given `Component`.
103 
104     class Info;
105 
106     /**
107      * Represents presence of different components in Active or Pending Operational Dataset.
108      *
109      */
110     class Components : public otOperationalDatasetComponents, public Clearable<Components>
111     {
112         friend class Info;
113 
114     public:
115         /**
116          * Indicates whether or not the specified `kComponent` is present in the Dataset.
117          *
118          * @tparam kComponent  The component to check.
119          *
120          * @retval TRUE   The component is present in the Dataset.
121          * @retval FALSE  The component is not present in the Dataset.
122          *
123          */
124         template <Component kComponent> bool IsPresent(void) const;
125 
126     private:
127         template <Component kComponent> void MarkAsPresent(void);
128     };
129 
130     /**
131      * Represents the information about the fields contained an Active or Pending Operational Dataset.
132      *
133      */
134     class Info : public otOperationalDataset, public Clearable<Info>
135     {
136     public:
137         /**
138          * Indicates whether or not the specified component is present in the Dataset.
139          *
140          * @tparam kComponent  The component to check.
141          *
142          * @retval TRUE   The component is present in the Dataset.
143          * @retval FALSE  The component is not present in the Dataset.
144          *
145          */
IsPresent(void) const146         template <Component kComponent> bool IsPresent(void) const { return GetComponents().IsPresent<kComponent>(); }
147 
148         /**
149          * Gets the specified component in the Dataset.
150          *
151          * @tparam  kComponent  The component to check.
152          *
153          * MUST be used when component is present in the Dataset, otherwise its behavior is undefined.
154          *
155          * @returns The component value.
156          *
157          */
158         template <Component kComponent> const typename TypeFor<kComponent>::Type &Get(void) const;
159 
160         /**
161          * Gets the specified component in the Dataset.
162          *
163          * @tparam  kComponent  The component to check.
164          *
165          * MUST be used when component is present in the Dataset, otherwise its behavior is undefined.
166          *
167          * @pram[out] aComponent  A reference to output the component value.
168          *
169          */
170         template <Component kComponent> void Get(typename TypeFor<kComponent>::Type &aComponent) const;
171 
172         /**
173          * Sets the specified component in the Dataset.
174          *
175          * @tparam  kComponent  The component to set.
176          *
177          * @param[in] aComponent   The component value.
178          *
179          */
Set(const typename TypeFor<kComponent>::Type & aComponent)180         template <Component kComponent> void Set(const typename TypeFor<kComponent>::Type &aComponent)
181         {
182             GetComponents().MarkAsPresent<kComponent>();
183             AsNonConst(Get<kComponent>()) = aComponent;
184         }
185 
186         /**
187          * Returns a reference to the specified component in the Dataset to be updated by caller.
188          *
189          * @tparam  kComponent  The component to set.
190          *
191          * @returns A reference to the component in the Dataset.
192          *
193          */
Update(void)194         template <Component kComponent> typename TypeFor<kComponent>::Type &Update(void)
195         {
196             GetComponents().MarkAsPresent<kComponent>();
197             return AsNonConst(Get<kComponent>());
198         }
199 
200         /**
201          * Populates the Dataset with random fields.
202          *
203          * The Network Key, PSKc, Mesh Local Prefix, PAN ID, and Extended PAN ID are generated randomly (crypto-secure)
204          * with Network Name set to "OpenThread-%04x" with PAN ID appended as hex. The Channel is chosen randomly from
205          * radio's preferred channel mask, Channel Mask is set from radio's supported mask, and Security Policy Flags
206          * from current `KeyManager` value.
207          *
208          * @param[in] aInstance    The OpenThread instance.
209          *
210          * @retval kErrorNone If the Dataset was generated successfully.
211          *
212          */
213         Error GenerateRandom(Instance &aInstance);
214 
215     private:
GetComponents(void)216         Components       &GetComponents(void) { return static_cast<Components &>(mComponents); }
GetComponents(void) const217         const Components &GetComponents(void) const { return static_cast<const Components &>(mComponents); }
218     };
219 
220     /**
221      * Initializes the object.
222      *
223      */
224     Dataset(void);
225 
226     /**
227      * Clears the Dataset.
228      *
229      */
Clear(void)230     void Clear(void) { mLength = 0; }
231 
232     /**
233      * Parses and validates all TLVs contained within the Dataset.
234      *
235      * Performs the following checks all TLVs in the Dataset:
236      *  - Ensures correct TLV format and expected minimum length for known TLV types that may appear in a Dataset.
237      *  - Validates TLV value when applicable (e.g., Channel TLV using a supported channel).
238      *  - Ensures no duplicate occurrence of same TLV type.
239      *
240      * @retval kErrorNone   Successfully validated all the TLVs in the Dataset.
241      * @retval kErrorParse  Dataset TLVs is not well-formed.
242      *
243      */
244     Error ValidateTlvs(void) const;
245 
246     /**
247      * Validates the format and value of a given MeshCoP TLV used in Dataset.
248      *
249      * TLV types that can appear in an Active or Pending Operational Dataset are validated. Other TLV types including
250      * unknown TLV types are considered as valid.
251      *
252      * @param[in]  aTlv    The TLV to validate.
253      *
254      * @retval  TRUE       The TLV format and value is valid, or TLV type is unknown (not supported in Dataset).
255      * @retval  FALSE      The TLV format or value is invalid.
256      *
257      */
258     static bool IsTlvValid(const Tlv &aTlv);
259 
260     /**
261      * Indicates whether or not a given TLV type is present in the Dataset.
262      *
263      * @param[in] aType  The TLV type to check.
264      *
265      * @retval TRUE    TLV with @p aType is present in the Dataset.
266      * @retval FALSE   TLV with @p aType is not present in the Dataset.
267      *
268      */
ContainsTlv(Tlv::Type aType) const269     bool ContainsTlv(Tlv::Type aType) const { return (FindTlv(aType) != nullptr); }
270 
271     /**
272      * Indicates whether or not a given TLV type is present in the Dataset.
273      *
274      * @tparam  aTlvType  The TLV type to check.
275      *
276      * @retval TRUE    TLV of @p aTlvType is present in the Dataset.
277      * @retval FALSE   TLV of @p aTlvType is not present in the Dataset.
278      *
279      */
Contains(void) const280     template <typename TlvType> bool Contains(void) const
281     {
282         return ContainsTlv(static_cast<Tlv::Type>(TlvType::kType));
283     }
284 
285     /**
286      * Indicates whether or not the Dataset contains all the TLVs from a given array.
287      *
288      * @param[in] aTlvTypes    An array of TLV types.
289      * @param[in] aLength      Length of @p aTlvTypes array.
290      *
291      * @retval TRUE    The Dataset contains all the TLVs in @p aTlvTypes array.
292      * @retval FALSE   The Dataset does not contain all the TLVs in @p aTlvTypes array.
293      *
294      */
295     bool ContainsAllTlvs(const Tlv::Type aTlvTypes[], uint8_t aLength) const;
296 
297     /**
298      * Indicates whether or not the Dataset contains all the required TLVs for an Active or Pending Dataset.
299      *
300      * @param[in] aType  The Dataset type, Active or Pending.
301      *
302      * @retval TRUE    The Dataset contains all the required TLVs for @p aType.
303      * @retval FALSE   The Dataset does not contain all the required TLVs for @p aType.
304      *
305      */
306     bool ContainsAllRequiredTlvsFor(Type aType) const;
307 
308     /**
309      * Searches for a given TLV type in the Dataset.
310      *
311      * @param[in] aType  The TLV type to find.
312      *
313      * @returns A pointer to the TLV or `nullptr` if not found.
314      *
315      */
FindTlv(Tlv::Type aType)316     Tlv *FindTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->FindTlv(aType)); }
317 
318     /**
319      * Searches for a given TLV type in the Dataset.
320      *
321      * @param[in] aType  The TLV type to find.
322      *
323      * @returns A pointer to the TLV or `nullptr` if not found.
324      *
325      */
326     const Tlv *FindTlv(Tlv::Type aType) const;
327 
328     /**
329      * Finds and reads a simple TLV in the Dataset.
330      *
331      * If the specified TLV type is not found, `kErrorNotFound` is reported.
332      *
333      * @tparam  SimpleTlvType   The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
334      *
335      * @param[out] aValue       A reference to return the read TLV value.
336      *
337      * @retval kErrorNone      Successfully found and read the TLV value. @p aValue is updated.
338      * @retval kErrorNotFound  Could not find the TLV in the Dataset.
339      *
340      */
Read(typename SimpleTlvType::ValueType & aValue) const341     template <typename SimpleTlvType> Error Read(typename SimpleTlvType::ValueType &aValue) const
342     {
343         const Tlv *tlv = FindTlv(static_cast<Tlv::Type>(SimpleTlvType::kType));
344 
345         return (tlv == nullptr) ? kErrorNotFound : (aValue = tlv->ReadValueAs<SimpleTlvType>(), kErrorNone);
346     }
347 
348     /**
349      * Finds and reads an `uint` TLV in the Dataset.
350      *
351      * If the specified TLV type is not found, `kErrorNotFound` is reported.
352      *
353      * @tparam  UintTlvType     The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
354      *
355      * @param[out] aValue       A reference to return the read TLV value.
356      *
357      * @retval kErrorNone      Successfully found and read the TLV value. @p aValue is updated.
358      * @retval kErrorNotFound  Could not find the TLV in the Dataset.
359      *
360      */
Read(typename UintTlvType::UintValueType & aValue) const361     template <typename UintTlvType> Error Read(typename UintTlvType::UintValueType &aValue) const
362     {
363         const Tlv *tlv = FindTlv(static_cast<Tlv::Type>(UintTlvType::kType));
364 
365         return (tlv == nullptr) ? kErrorNotFound : (aValue = tlv->ReadValueAs<UintTlvType>(), kErrorNone);
366     }
367 
368     /**
369      * Writes a TLV to the Dataset.
370      *
371      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
372      *
373      * @param[in] aTlv     A reference to the TLV.
374      *
375      * @retval kErrorNone    Successfully updated the TLV.
376      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
377      *
378      */
379     Error WriteTlv(const Tlv &aTlv);
380 
381     /**
382      * Writes a TLV in the Dataset.
383      *
384      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
385      *
386      * @param[in]  aType     The TLV type.
387      * @param[in]  aValue    A pointer to a buffer containing the TLV value.
388      * @param[in]  aLength   The TLV length.
389      *
390      * @retval kErrorNone    Successfully updated the TLV.
391      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
392      *
393      */
394     Error WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
395 
396     /**
397      * Writes a simple TLV in the Dataset.
398      *
399      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
400      *
401      * @tparam  SimpleTlvType   The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
402      *
403      * @param[in] aValue   The TLV value.
404      *
405      * @retval kErrorNone    Successfully updated the TLV.
406      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
407      *
408      */
Write(const typename SimpleTlvType::ValueType & aValue)409     template <typename SimpleTlvType> Error Write(const typename SimpleTlvType::ValueType &aValue)
410     {
411         return WriteTlv(static_cast<Tlv::Type>(SimpleTlvType::kType), &aValue, sizeof(aValue));
412     }
413 
414     /**
415      * Writes a `uint` TLV in the Dataset.
416      *
417      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
418      *
419      * @tparam  UintTlvType     The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
420      *
421      * @param[in]  aValue   The TLV value.
422      *
423      * @retval kErrorNone    Successfully updated the TLV.
424      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
425      *
426      */
Write(typename UintTlvType::UintValueType aValue)427     template <typename UintTlvType> Error Write(typename UintTlvType::UintValueType aValue)
428     {
429         typename UintTlvType::UintValueType value = BigEndian::HostSwap(aValue);
430 
431         return WriteTlv(static_cast<Tlv::Type>(UintTlvType::kType), &value, sizeof(value));
432     }
433 
434     /**
435      * Writes TLVs parsed from a given Dataset into this Dataset.
436      *
437      * TLVs from @p aDataset are parsed and written in the current Dataset. If the same TLV already exists, it will be
438      * replaced. Otherwise, the TLV will be appended.
439      *
440      * @param[in] aDataset   A Dataset.
441      *
442      * @retval kErrorNone    Successfully merged TLVs from @p Dataset into this Dataset.
443      * @retval kErrorParse   The @p aDataset is not valid.
444      * @retval kErrorNoBufs  Could not add the TLVs due to insufficient buffer space.
445      *
446      */
447     Error WriteTlvsFrom(const Dataset &aDataset);
448 
449     /**
450      * Writes TLVs parsed from a given buffer containing a sequence of TLVs into this Dataset.
451      *
452      * TLVs from @p aTlvs buffer are parsed and written in the current Dataset. If the same TLV already exists, it will
453      * be replaced. Otherwise, the TLV will be appended.
454      *
455      * @param[in] aTlvs     A pointer to a buffer containing TLVs.
456      * @param[in] aLength   Number of bytes in @p aTlvs buffer.
457      *
458      * @retval kErrorNone    Successfully merged TLVs from @p Dataset into this Dataset.
459      * @retval kErrorParse   The @p aTlvs is not valid.
460      * @retval kErrorNoBufs  Could not add the TLVs due to insufficient buffer space.
461      *
462      */
463     Error WriteTlvsFrom(const uint8_t *aTlvs, uint8_t aLength);
464 
465     /**
466      * Writes TLVs corresponding to the components in a given `Dataset::Info` into this Dataset.
467      *
468      * If the same TLV already exists, it will be replaced. Otherwise the TLV will be appended.
469      *
470      * @param[in] aDataseInfo     A `Dataset::Info`.
471      *
472      * @retval kErrorNone    Successfully merged TLVs from @p aDataseInfo into this Dataset.
473      * @retval kErrorNoBufs  Could not add the TLVs due to insufficient buffer space.
474      *
475      */
476     Error WriteTlvsFrom(const Dataset::Info &aDatasetInfo);
477 
478     /**
479      * Appends a given sequence of TLVs to the Dataset.
480      *
481      * @note Unlike `WriteTlvsFrom()`, this method does not validate the @p aTlvs to be well-formed or check that there
482      * are no duplicates. It is up to caller to validate the resulting `Dataset` (e.g., using `ValidateTlvs()`) if
483      * desired.
484      *
485      * @param[in] aTlvs     A pointer to a buffer containing TLVs.
486      * @param[in] aLength   Number of bytes in @p aTlvs buffer.
487      *
488      * @retval kErrorNone    Successfully merged TLVs from @p Dataset into this Dataset.
489      * @retval kErrorNoBufs  Could not append the TLVs due to insufficient buffer space.
490      *
491      */
492     Error AppendTlvsFrom(const uint8_t *aTlvs, uint8_t aLength);
493 
494     /**
495      * Removes a TLV from the Dataset.
496      *
497      * If the Dataset does not contain the given TLV type, no action is performed.
498      *
499      * @param[in] aType  The TLV type to remove.
500      *
501      */
502     void RemoveTlv(Tlv::Type aType);
503 
504     /**
505      * Reads the Timestamp TLV (Active or Pending).
506      *
507      * @param[in]  aType       The timestamp type, active or pending.
508      * @param[out] aTimestamp  A reference to a `Timestamp` to output the value.
509      *
510      * @retval kErrorNone      Timestamp was read successfully. @p aTimestamp is updated.
511      * @retval kErrorNotFound  Could not find the requested Timestamp TLV.
512      *
513      */
514     Error ReadTimestamp(Type aType, Timestamp &aTimestamp) const;
515 
516     /**
517      * Writes the Timestamp TLV (Active or Pending).
518      *
519      * If the TLV already exists, it will be replaced. Otherwise, the TLV will be appended.
520      *
521      * @param[in] aType       The timestamp type, active or pending.
522      * @param[in] aTimestamp  The timestamp value.
523      *
524      * @retval kErrorNone    Successfully updated the Timestamp TLV.
525      * @retval kErrorNoBufs  Could not append the Timestamp TLV due to insufficient buffer space.
526      *
527      */
528     Error WriteTimestamp(Type aType, const Timestamp &aTimestamp);
529 
530     /**
531      * Removes the Timestamp TLV (Active or Pending) from the Dataset.
532      *
533      * @param[in] aType       The timestamp type, active or pending.
534      *
535      */
536     void RemoveTimestamp(Type aType);
537 
538     /**
539      * Returns a pointer to the byte representation of the Dataset.
540      *
541      * @returns A pointer to the byte representation of the Dataset.
542      *
543      */
GetBytes(void)544     uint8_t *GetBytes(void) { return mTlvs; }
545 
546     /**
547      * Returns a pointer to the byte representation of the Dataset.
548      *
549      * @returns A pointer to the byte representation of the Dataset.
550      *
551      */
GetBytes(void) const552     const uint8_t *GetBytes(void) const { return mTlvs; }
553 
554     /**
555      * Converts the TLV representation to structure representation.
556      *
557      * @param[out] aDatasetInfo  A reference to `Info` object to output the Dataset.
558      *
559      */
560     void ConvertTo(Info &aDatasetInfo) const;
561 
562     /**
563      * Converts the TLV representation to structure representation.
564      *
565      * @param[out] aTlvs  A reference to output the Dataset as a sequence of TLVs.
566      *
567      */
568     void ConvertTo(Tlvs &aTlvs) const;
569 
570     /**
571      * Returns the Dataset length in bytes.
572      *
573      * @returns The Dataset length in bytes.
574      *
575      */
GetLength(void) const576     uint8_t GetLength(void) const { return mLength; }
577 
578     /**
579      * Sets the Dataset size in bytes.
580      *
581      * @param[in] aSize  The Dataset size in bytes.
582      *
583      */
SetLength(uint8_t aLength)584     void SetLength(uint8_t aLength) { mLength = aLength; }
585 
586     /**
587      * Returns the local time the dataset was last updated.
588      *
589      * @returns The local time the dataset was last updated.
590      *
591      */
GetUpdateTime(void) const592     TimeMilli GetUpdateTime(void) const { return mUpdateTime; }
593 
594     /**
595      * Sets this Dataset using an existing Dataset.
596      *
597      * @param[in]  aDataset  The input Dataset.
598      *
599      */
600     void SetFrom(const Dataset &aDataset);
601 
602     /**
603      * Sets the Dataset from a given structure representation.
604      *
605      * @param[in]  aDatasetInfo  The input Dataset as `Dataset::Info`.
606      *
607      */
608     void SetFrom(const Info &aDatasetInfo);
609 
610     /**
611      * Sets the Dataset from a given sequence of TLVs.
612      *
613      * @param[in]  aTlvs          The input Dataset as `Tlvs`.
614      *
615      * @retval kErrorNone         Successfully set the Dataset.
616      * @retval kErrorInvalidArgs  The @p aTlvs is invalid and its length is longer than `kMaxLength`.
617      *
618      */
619     Error SetFrom(const Tlvs &aTlvs);
620 
621     /**
622      * Sets the Dataset from a buffer containing a sequence of TLVs.
623      *
624      * @param[in] aTlvs     A pointer to a buffer containing TLVs.
625      * @param[in] aLength   Number of bytes in @p aTlvs buffer.
626      *
627      * @retval kErrorNone         Successfully set the Dataset.
628      * @retval kErrorInvalidArgs  @p aLength is longer than `kMaxLength`.
629      *
630      */
631     Error SetFrom(const uint8_t *aTlvs, uint8_t aLength);
632 
633     /**
634      * Sets the Dataset by reading the TLVs bytes from given message.
635      *
636      * @param[in] aMessage       The message to read from.
637      * @param[in] aOffsetRange   The offset range in @p aMessage to read the Dataset TLVs.
638      *
639      * @retval kErrorNone    Successfully set the Dataset.
640      * @retval kInvalidArgs  The given offset range length is longer than `kMaxLength`.
641      * @retval kErrorParse   Could not read or parse the dataset from @p aMessage.
642      *
643      */
644     Error SetFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
645 
646     /**
647      * Returns a pointer to the start of Dataset TLVs sequence.
648      *
649      * @return  A pointer to the start of Dataset TLVs sequence.
650      *
651      */
GetTlvsStart(void)652     Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); }
653 
654     /**
655      * Returns a pointer to the start of Dataset TLVs sequence.
656      *
657      * @return  A pointer to start of Dataset TLVs sequence.
658      *
659      */
GetTlvsStart(void) const660     const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); }
661 
662     /**
663      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
664      *
665      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
666      *
667      * @return  A pointer to past-the-end of Dataset TLVs sequence.
668      *
669      */
GetTlvsEnd(void)670     Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); }
671 
672     /**
673      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
674      *
675      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
676      *
677      * @return  A pointer to past-the-end of Dataset TLVs sequence.
678      *
679      */
GetTlvsEnd(void) const680     const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); }
681 
682     /**
683      * Determines whether this Dataset is a subset of another Dataset.
684      *
685      * The Dataset is considered a subset if all of its TLVs, excluding Active/Pending Timestamp and Delay Timer TLVs,
686      * are present in the @p aOther Dataset and the TLV values match exactly.
687      *
688      * @param[in] aOther   The other Dataset to check against.
689      *
690      * @retval TRUE   The current Dataset is a subset of @p aOther.
691      * @retval FALSE  The current Dataset is not a subset of @p aOther.
692      *
693      */
694     bool IsSubsetOf(const Dataset &aOther) const;
695 
696     /**
697      * Converts a Dataset Type to a string.
698      *
699      * @param[in]  aType   A Dataset type.
700      *
701      */
702     static const char *TypeToString(Type aType);
703 
704 private:
705     void RemoveTlv(Tlv *aTlv);
706 
TimestampTlvFor(Type aType)707     static Tlv::Type TimestampTlvFor(Type aType)
708     {
709         return (aType == kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp;
710     }
711 
712     uint8_t   mTlvs[kMaxLength];
713     uint8_t   mLength;
714     TimeMilli mUpdateTime; // Local time last updated
715 };
716 
717 //---------------------------------------------------------------------------------------------------------------------
718 // Template specializations
719 
720 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
721 // `Dataset::Components::IsPresent()` and `Dataset::Components::MarkAsPresent()`
722 
723 #define DefineIsPresentAndMarkAsPresent(Component)                                            \
724     template <> inline bool Dataset::Components::IsPresent<Dataset::k##Component>(void) const \
725     {                                                                                         \
726         return mIs##Component##Present;                                                       \
727     }                                                                                         \
728                                                                                               \
729     template <> inline void Dataset::Components::MarkAsPresent<Dataset::k##Component>(void)   \
730     {                                                                                         \
731         mIs##Component##Present = true;                                                       \
732     }
733 
734 // clang-format off
735 
736 DefineIsPresentAndMarkAsPresent(ActiveTimestamp)
737 DefineIsPresentAndMarkAsPresent(PendingTimestamp)
738 DefineIsPresentAndMarkAsPresent(NetworkKey)
739 DefineIsPresentAndMarkAsPresent(NetworkName)
740 DefineIsPresentAndMarkAsPresent(ExtendedPanId)
741 DefineIsPresentAndMarkAsPresent(MeshLocalPrefix)
742 DefineIsPresentAndMarkAsPresent(Delay)
743 DefineIsPresentAndMarkAsPresent(PanId)
744 DefineIsPresentAndMarkAsPresent(Channel)
745 DefineIsPresentAndMarkAsPresent(Pskc)
746 DefineIsPresentAndMarkAsPresent(SecurityPolicy)
747 DefineIsPresentAndMarkAsPresent(ChannelMask)
748 
749 #undef DefineIsPresentAndMarkAsPresent
750 
751 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
752 // `Dataset::TypeFor<>`
753 
754 template <> struct Dataset::TypeFor<Dataset::kActiveTimestamp>  { using Type = Timestamp; };
755 template <> struct Dataset::TypeFor<Dataset::kPendingTimestamp> { using Type = Timestamp; };
756 template <> struct Dataset::TypeFor<Dataset::kNetworkKey>       { using Type = NetworkKey; };
757 template <> struct Dataset::TypeFor<Dataset::kNetworkName>      { using Type = NetworkName; };
758 template <> struct Dataset::TypeFor<Dataset::kExtendedPanId>    { using Type = ExtendedPanId; };
759 template <> struct Dataset::TypeFor<Dataset::kMeshLocalPrefix>  { using Type = Ip6::NetworkPrefix; };
760 template <> struct Dataset::TypeFor<Dataset::kDelay>            { using Type = uint32_t; };
761 template <> struct Dataset::TypeFor<Dataset::kPanId>            { using Type = Mac::PanId; };
762 template <> struct Dataset::TypeFor<Dataset::kChannel>          { using Type = uint16_t; };
763 template <> struct Dataset::TypeFor<Dataset::kPskc>             { using Type = Pskc; };
764 template <> struct Dataset::TypeFor<Dataset::kSecurityPolicy>   { using Type = SecurityPolicy; };
765 template <> struct Dataset::TypeFor<Dataset::kChannelMask>      { using Type = uint32_t; };
766 
767 // clang-format on
768 
769 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
770 // Dataset::Info::Get<>()
771 
Get(void) const772 template <> inline const NetworkKey &Dataset::Info::Get<Dataset::kNetworkKey>(void) const
773 {
774     return AsCoreType(&mNetworkKey);
775 }
776 
Get(void) const777 template <> inline const NetworkName &Dataset::Info::Get<Dataset::kNetworkName>(void) const
778 {
779     return AsCoreType(&mNetworkName);
780 }
781 
Get(void) const782 template <> inline const ExtendedPanId &Dataset::Info::Get<Dataset::kExtendedPanId>(void) const
783 {
784     return AsCoreType(&mExtendedPanId);
785 }
786 
Get(void) const787 template <> inline const Ip6::NetworkPrefix &Dataset::Info::Get<Dataset::kMeshLocalPrefix>(void) const
788 {
789     return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix);
790 }
791 
Get(void) const792 template <> inline const uint32_t &Dataset::Info::Get<Dataset::kDelay>(void) const { return mDelay; }
793 
Get(void) const794 template <> inline const Mac::PanId &Dataset::Info::Get<Dataset::kPanId>(void) const { return mPanId; }
795 
Get(void) const796 template <> inline const uint16_t &Dataset::Info::Get<Dataset::kChannel>(void) const { return mChannel; }
797 
Get(void) const798 template <> inline const Pskc &Dataset::Info::Get<Dataset::kPskc>(void) const { return AsCoreType(&mPskc); }
799 
Get(void) const800 template <> inline const SecurityPolicy &Dataset::Info::Get<Dataset::kSecurityPolicy>(void) const
801 {
802     return AsCoreType(&mSecurityPolicy);
803 }
804 
Get(void) const805 template <> inline const uint32_t &Dataset::Info::Get<Dataset::kChannelMask>(void) const { return mChannelMask; }
806 
807 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
808 // Active and Pending Timestamp
809 
Get(Timestamp & aTimestamp) const810 template <> inline void Dataset::Info::Get<Dataset::kActiveTimestamp>(Timestamp &aTimestamp) const
811 {
812     aTimestamp.SetFrom(mActiveTimestamp);
813 }
814 
Get(Timestamp & aTimestamp) const815 template <> inline void Dataset::Info::Get<Dataset::kPendingTimestamp>(Timestamp &aTimestamp) const
816 {
817     aTimestamp.SetFrom(mPendingTimestamp);
818 }
819 
Set(const Timestamp & aTimestamp)820 template <> inline void Dataset::Info::Set<Dataset::kActiveTimestamp>(const Timestamp &aTimestamp)
821 {
822     GetComponents().MarkAsPresent<kActiveTimestamp>();
823     aTimestamp.ConvertTo(mActiveTimestamp);
824 }
825 
Set(const Timestamp & aTimestamp)826 template <> inline void Dataset::Info::Set<Dataset::kPendingTimestamp>(const Timestamp &aTimestamp)
827 {
828     GetComponents().MarkAsPresent<kPendingTimestamp>();
829     aTimestamp.ConvertTo(mPendingTimestamp);
830 }
831 
832 } // namespace MeshCoP
833 
834 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
835 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
836 
837 } // namespace ot
838 
839 #endif // MESHCOP_DATASET_HPP_
840