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]  aOffset   The offset in @p aMessage to start reading the Dataset TLVs.
638      * @param[in]  aLength   The dataset length in bytes.
639      *
640      * @retval kErrorNone    Successfully set the Dataset.
641      * @retval kInvalidArgs  The @p aLength is longer than `kMaxLength`.
642      * @retval kErrorParse   Could not read or parse the dataset from @p aMessage.
643      *
644      */
645     Error SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
646 
647     /**
648      * Returns a pointer to the start of Dataset TLVs sequence.
649      *
650      * @return  A pointer to the start of Dataset TLVs sequence.
651      *
652      */
GetTlvsStart(void)653     Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); }
654 
655     /**
656      * Returns a pointer to the start of Dataset TLVs sequence.
657      *
658      * @return  A pointer to start of Dataset TLVs sequence.
659      *
660      */
GetTlvsStart(void) const661     const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); }
662 
663     /**
664      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
665      *
666      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
667      *
668      * @return  A pointer to past-the-end of Dataset TLVs sequence.
669      *
670      */
GetTlvsEnd(void)671     Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); }
672 
673     /**
674      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
675      *
676      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
677      *
678      * @return  A pointer to past-the-end of Dataset TLVs sequence.
679      *
680      */
GetTlvsEnd(void) const681     const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); }
682 
683     /**
684      * Determines whether this Dataset is a subset of another Dataset.
685      *
686      * The Dataset is considered a subset if all of its TLVs, excluding Active/Pending Timestamp and Delay Timer TLVs,
687      * are present in the @p aOther Dataset and the TLV values match exactly.
688      *
689      * @param[in] aOther   The other Dataset to check against.
690      *
691      * @retval TRUE   The current Dataset is a subset of @p aOther.
692      * @retval FALSE  The current Dataset is not a subset of @p aOther.
693      *
694      */
695     bool IsSubsetOf(const Dataset &aOther) const;
696 
697     /**
698      * Converts a Dataset Type to a string.
699      *
700      * @param[in]  aType   A Dataset type.
701      *
702      */
703     static const char *TypeToString(Type aType);
704 
705 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
706 
707     /**
708      * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero.
709      *
710      * If the Dataset does not contain the @p aTlvType, no action is performed.
711      *
712      * @param[in] aTlvType    The TLV type.
713      * @param[in] aKeyRef     The `KeyRef` to use with secure storage.
714      *
715      */
716     void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
717 
718     /**
719      * Reads and updates a given TLV value in Dataset from secure storage.
720      *
721      * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned.
722      *
723      * @param[in] aTlvType    The TLV type.
724      * @param[in] aKeyRef     The `KeyRef` to use with secure storage.
725      *
726      * @retval kErrorNone    Successfully read the TLV value from secure storage and updated the Dataset.
727      * @retval KErrorFailed  Could not read the @aKeyRef from secure storage.
728      *
729      */
730     Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
731 
732 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
733 
734 private:
735     void RemoveTlv(Tlv *aTlv);
736 
TimestampTlvFor(Type aType)737     static Tlv::Type TimestampTlvFor(Type aType)
738     {
739         return (aType == kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp;
740     }
741 
742     uint8_t   mTlvs[kMaxLength];
743     uint8_t   mLength;
744     TimeMilli mUpdateTime; // Local time last updated
745 };
746 
747 //---------------------------------------------------------------------------------------------------------------------
748 // Template specializations
749 
750 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
751 // `Dataset::Components::IsPresent()` and `Dataset::Components::MarkAsPresent()`
752 
753 #define DefineIsPresentAndMarkAsPresent(Component)                                            \
754     template <> inline bool Dataset::Components::IsPresent<Dataset::k##Component>(void) const \
755     {                                                                                         \
756         return mIs##Component##Present;                                                       \
757     }                                                                                         \
758                                                                                               \
759     template <> inline void Dataset::Components::MarkAsPresent<Dataset::k##Component>(void)   \
760     {                                                                                         \
761         mIs##Component##Present = true;                                                       \
762     }
763 
764 // clang-format off
765 
766 DefineIsPresentAndMarkAsPresent(ActiveTimestamp)
767 DefineIsPresentAndMarkAsPresent(PendingTimestamp)
768 DefineIsPresentAndMarkAsPresent(NetworkKey)
769 DefineIsPresentAndMarkAsPresent(NetworkName)
770 DefineIsPresentAndMarkAsPresent(ExtendedPanId)
771 DefineIsPresentAndMarkAsPresent(MeshLocalPrefix)
772 DefineIsPresentAndMarkAsPresent(Delay)
773 DefineIsPresentAndMarkAsPresent(PanId)
774 DefineIsPresentAndMarkAsPresent(Channel)
775 DefineIsPresentAndMarkAsPresent(Pskc)
776 DefineIsPresentAndMarkAsPresent(SecurityPolicy)
777 DefineIsPresentAndMarkAsPresent(ChannelMask)
778 
779 #undef DefineIsPresentAndMarkAsPresent
780 
781 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
782 // `Dataset::TypeFor<>`
783 
784 template <> struct Dataset::TypeFor<Dataset::kActiveTimestamp>  { using Type = Timestamp; };
785 template <> struct Dataset::TypeFor<Dataset::kPendingTimestamp> { using Type = Timestamp; };
786 template <> struct Dataset::TypeFor<Dataset::kNetworkKey>       { using Type = NetworkKey; };
787 template <> struct Dataset::TypeFor<Dataset::kNetworkName>      { using Type = NetworkName; };
788 template <> struct Dataset::TypeFor<Dataset::kExtendedPanId>    { using Type = ExtendedPanId; };
789 template <> struct Dataset::TypeFor<Dataset::kMeshLocalPrefix>  { using Type = Ip6::NetworkPrefix; };
790 template <> struct Dataset::TypeFor<Dataset::kDelay>            { using Type = uint32_t; };
791 template <> struct Dataset::TypeFor<Dataset::kPanId>            { using Type = Mac::PanId; };
792 template <> struct Dataset::TypeFor<Dataset::kChannel>          { using Type = uint16_t; };
793 template <> struct Dataset::TypeFor<Dataset::kPskc>             { using Type = Pskc; };
794 template <> struct Dataset::TypeFor<Dataset::kSecurityPolicy>   { using Type = SecurityPolicy; };
795 template <> struct Dataset::TypeFor<Dataset::kChannelMask>      { using Type = uint32_t; };
796 
797 // clang-format on
798 
799 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
800 // Dataset::Info::Get<>()
801 
Get(void) const802 template <> inline const NetworkKey &Dataset::Info::Get<Dataset::kNetworkKey>(void) const
803 {
804     return AsCoreType(&mNetworkKey);
805 }
806 
Get(void) const807 template <> inline const NetworkName &Dataset::Info::Get<Dataset::kNetworkName>(void) const
808 {
809     return AsCoreType(&mNetworkName);
810 }
811 
Get(void) const812 template <> inline const ExtendedPanId &Dataset::Info::Get<Dataset::kExtendedPanId>(void) const
813 {
814     return AsCoreType(&mExtendedPanId);
815 }
816 
Get(void) const817 template <> inline const Ip6::NetworkPrefix &Dataset::Info::Get<Dataset::kMeshLocalPrefix>(void) const
818 {
819     return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix);
820 }
821 
Get(void) const822 template <> inline const uint32_t &Dataset::Info::Get<Dataset::kDelay>(void) const { return mDelay; }
823 
Get(void) const824 template <> inline const Mac::PanId &Dataset::Info::Get<Dataset::kPanId>(void) const { return mPanId; }
825 
Get(void) const826 template <> inline const uint16_t &Dataset::Info::Get<Dataset::kChannel>(void) const { return mChannel; }
827 
Get(void) const828 template <> inline const Pskc &Dataset::Info::Get<Dataset::kPskc>(void) const { return AsCoreType(&mPskc); }
829 
Get(void) const830 template <> inline const SecurityPolicy &Dataset::Info::Get<Dataset::kSecurityPolicy>(void) const
831 {
832     return AsCoreType(&mSecurityPolicy);
833 }
834 
Get(void) const835 template <> inline const uint32_t &Dataset::Info::Get<Dataset::kChannelMask>(void) const { return mChannelMask; }
836 
837 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
838 // Active and Pending Timestamp
839 
Get(Timestamp & aTimestamp) const840 template <> inline void Dataset::Info::Get<Dataset::kActiveTimestamp>(Timestamp &aTimestamp) const
841 {
842     aTimestamp.SetFrom(mActiveTimestamp);
843 }
844 
Get(Timestamp & aTimestamp) const845 template <> inline void Dataset::Info::Get<Dataset::kPendingTimestamp>(Timestamp &aTimestamp) const
846 {
847     aTimestamp.SetFrom(mPendingTimestamp);
848 }
849 
Set(const Timestamp & aTimestamp)850 template <> inline void Dataset::Info::Set<Dataset::kActiveTimestamp>(const Timestamp &aTimestamp)
851 {
852     GetComponents().MarkAsPresent<kActiveTimestamp>();
853     aTimestamp.ConvertTo(mActiveTimestamp);
854 }
855 
Set(const Timestamp & aTimestamp)856 template <> inline void Dataset::Info::Set<Dataset::kPendingTimestamp>(const Timestamp &aTimestamp)
857 {
858     GetComponents().MarkAsPresent<kPendingTimestamp>();
859     aTimestamp.ConvertTo(mPendingTimestamp);
860 }
861 
862 } // namespace MeshCoP
863 
864 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
865 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
866 
867 } // namespace ot
868 
869 #endif // MESHCOP_DATASET_HPP_
870