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