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  * This class represents MeshCop Dataset.
57  *
58  */
59 class Dataset
60 {
61     friend class DatasetLocal;
62 
63 public:
64     static constexpr uint8_t kMaxSize      = OT_OPERATIONAL_DATASET_MAX_LENGTH; ///< Max size of MeshCoP Dataset (bytes)
65     static constexpr uint8_t kMaxValueSize = 16;                                ///< Max size of a TLV value (bytes)
66     static constexpr uint8_t kMaxGetTypes  = 64;                                ///< Max number of types in MGMT_GET.req
67 
68     /**
69      * This enumeration represents the Dataset type (active or pending).
70      *
71      */
72     enum Type : uint8_t
73     {
74         kActive,  ///< Active Dataset
75         kPending, ///< Pending Dataset
76     };
77 
78     /**
79      * This class represents presence of different components in Active or Pending Operational Dataset.
80      *
81      */
82     class Components : public otOperationalDatasetComponents, public Clearable<Components>
83     {
84     public:
85         /**
86          * This method indicates whether or not the Active Timestamp is present in the Dataset.
87          *
88          * @returns TRUE if Active Timestamp is present, FALSE otherwise.
89          *
90          */
IsActiveTimestampPresent(void) const91         bool IsActiveTimestampPresent(void) const { return mIsActiveTimestampPresent; }
92 
93         /**
94          * This method indicates whether or not the Pending Timestamp is present in the Dataset.
95          *
96          * @returns TRUE if Pending Timestamp is present, FALSE otherwise.
97          *
98          */
IsPendingTimestampPresent(void) const99         bool IsPendingTimestampPresent(void) const { return mIsPendingTimestampPresent; }
100 
101         /**
102          * This method indicates whether or not the Network Key is present in the Dataset.
103          *
104          * @returns TRUE if Network Key is present, FALSE otherwise.
105          *
106          */
IsNetworkKeyPresent(void) const107         bool IsNetworkKeyPresent(void) const { return mIsNetworkKeyPresent; }
108 
109         /**
110          * This method indicates whether or not the Network Name is present in the Dataset.
111          *
112          * @returns TRUE if Network Name is present, FALSE otherwise.
113          *
114          */
IsNetworkNamePresent(void) const115         bool IsNetworkNamePresent(void) const { return mIsNetworkNamePresent; }
116 
117         /**
118          * This method indicates whether or not the Extended PAN ID is present in the Dataset.
119          *
120          * @returns TRUE if Extended PAN ID is present, FALSE otherwise.
121          *
122          */
IsExtendedPanIdPresent(void) const123         bool IsExtendedPanIdPresent(void) const { return mIsExtendedPanIdPresent; }
124 
125         /**
126          * This method indicates whether or not the Mesh Local Prefix is present in the Dataset.
127          *
128          * @returns TRUE if Mesh Local Prefix is present, FALSE otherwise.
129          *
130          */
IsMeshLocalPrefixPresent(void) const131         bool IsMeshLocalPrefixPresent(void) const { return mIsMeshLocalPrefixPresent; }
132 
133         /**
134          * This method indicates whether or not the Delay Timer is present in the Dataset.
135          *
136          * @returns TRUE if Delay Timer is present, FALSE otherwise.
137          *
138          */
IsDelayPresent(void) const139         bool IsDelayPresent(void) const { return mIsDelayPresent; }
140 
141         /**
142          * This method indicates whether or not the PAN ID is present in the Dataset.
143          *
144          * @returns TRUE if PAN ID is present, FALSE otherwise.
145          *
146          */
IsPanIdPresent(void) const147         bool IsPanIdPresent(void) const { return mIsPanIdPresent; }
148 
149         /**
150          * This method indicates whether or not the Channel is present in the Dataset.
151          *
152          * @returns TRUE if Channel is present, FALSE otherwise.
153          *
154          */
IsChannelPresent(void) const155         bool IsChannelPresent(void) const { return mIsChannelPresent; }
156 
157         /**
158          * This method indicates whether or not the PSKc is present in the Dataset.
159          *
160          * @returns TRUE if PSKc is present, FALSE otherwise.
161          *
162          */
IsPskcPresent(void) const163         bool IsPskcPresent(void) const { return mIsPskcPresent; }
164 
165         /**
166          * This method indicates whether or not the Security Policy is present in the Dataset.
167          *
168          * @returns TRUE if Security Policy is present, FALSE otherwise.
169          *
170          */
IsSecurityPolicyPresent(void) const171         bool IsSecurityPolicyPresent(void) const { return mIsSecurityPolicyPresent; }
172 
173         /**
174          * This method indicates whether or not the Channel Mask is present in the Dataset.
175          *
176          * @returns TRUE if Channel Mask is present, FALSE otherwise.
177          *
178          */
IsChannelMaskPresent(void) const179         bool IsChannelMaskPresent(void) const { return mIsChannelMaskPresent; }
180     };
181 
182     /**
183      * This type represents the information about the fields contained an Active or Pending Operational Dataset.
184      *
185      */
186     class Info : public otOperationalDataset, public Clearable<Info>
187     {
188     public:
189         /**
190          * This method indicates whether or not the Active Timestamp is present in the Dataset.
191          *
192          * @returns TRUE if Active Timestamp is present, FALSE otherwise.
193          *
194          */
IsActiveTimestampPresent(void) const195         bool IsActiveTimestampPresent(void) const { return mComponents.mIsActiveTimestampPresent; }
196 
197         /**
198          * This method gets the Active Timestamp in the Dataset.
199          *
200          * This method MUST be used when Active Timestamp component is present in the Dataset, otherwise its behavior is
201          * undefined.
202          *
203          * @returns The Active Timestamp in the Dataset.
204          *
205          */
GetActiveTimestamp(Timestamp & aTimestamp) const206         void GetActiveTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mActiveTimestamp); }
207 
208         /**
209          * This method sets the Active Timestamp in the Dataset.
210          *
211          * @param[in] aTimestamp   A Timestamp value.
212          *
213          */
SetActiveTimestamp(const Timestamp & aTimestamp)214         void SetActiveTimestamp(const Timestamp &aTimestamp)
215         {
216             aTimestamp.ConvertTo(mActiveTimestamp);
217             mComponents.mIsActiveTimestampPresent = true;
218         }
219 
220         /**
221          * This method indicates whether or not the Pending Timestamp is present in the Dataset.
222          *
223          * @returns TRUE if Pending Timestamp is present, FALSE otherwise.
224          *
225          */
IsPendingTimestampPresent(void) const226         bool IsPendingTimestampPresent(void) const { return mComponents.mIsPendingTimestampPresent; }
227 
228         /**
229          * This method gets the Pending Timestamp in the Dataset.
230          *
231          * This method MUST be used when Pending Timestamp component is present in the Dataset, otherwise its behavior
232          * is undefined.
233          *
234          * @returns The Pending Timestamp in the Dataset.
235          *
236          */
GetPendingTimestamp(Timestamp & aTimestamp) const237         void GetPendingTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mPendingTimestamp); }
238 
239         /**
240          * This method sets the Pending Timestamp in the Dataset.
241          *
242          * @param[in] aTimestamp   A Timestamp value.
243          *
244          */
SetPendingTimestamp(const Timestamp & aTimestamp)245         void SetPendingTimestamp(const Timestamp &aTimestamp)
246         {
247             aTimestamp.ConvertTo(mPendingTimestamp);
248             mComponents.mIsPendingTimestampPresent = true;
249         }
250 
251         /**
252          * This method indicates whether or not the Network Key is present in the Dataset.
253          *
254          * @returns TRUE if Network Key is present, FALSE otherwise.
255          *
256          */
IsNetworkKeyPresent(void) const257         bool IsNetworkKeyPresent(void) const { return mComponents.mIsNetworkKeyPresent; }
258 
259         /**
260          * This method gets the Network Key in the Dataset.
261          *
262          * This method MUST be used when Network Key component is present in the Dataset, otherwise its behavior
263          * is undefined.
264          *
265          * @returns The Network Key in the Dataset.
266          *
267          */
GetNetworkKey(void) const268         const NetworkKey &GetNetworkKey(void) const { return AsCoreType(&mNetworkKey); }
269 
270         /**
271          * This method sets the Network Key in the Dataset.
272          *
273          * @param[in] aNetworkKey  A Network Key.
274          *
275          */
SetNetworkKey(const NetworkKey & aNetworkKey)276         void SetNetworkKey(const NetworkKey &aNetworkKey)
277         {
278             mNetworkKey                      = aNetworkKey;
279             mComponents.mIsNetworkKeyPresent = true;
280         }
281 
282         /**
283          * This method returns a reference to the Network Key in the Dataset to be updated by caller.
284          *
285          * @returns A reference to the Network Key in the Dataset.
286          *
287          */
UpdateNetworkKey(void)288         NetworkKey &UpdateNetworkKey(void)
289         {
290             mComponents.mIsNetworkKeyPresent = true;
291             return AsCoreType(&mNetworkKey);
292         }
293 
294         /**
295          * This method indicates whether or not the Network Name is present in the Dataset.
296          *
297          * @returns TRUE if Network Name is present, FALSE otherwise.
298          *
299          */
IsNetworkNamePresent(void) const300         bool IsNetworkNamePresent(void) const { return mComponents.mIsNetworkNamePresent; }
301 
302         /**
303          * This method gets the Network Name in the Dataset.
304          *
305          * This method MUST be used when Network Name component is present in the Dataset, otherwise its behavior is
306          * undefined.
307          *
308          * @returns The Network Name in the Dataset.
309          *
310          */
GetNetworkName(void) const311         const NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); }
312 
313         /**
314          * This method sets the Network Name in the Dataset.
315          *
316          * @param[in] aNetworkNameData   A Network Name Data.
317          *
318          */
SetNetworkName(const NameData & aNetworkNameData)319         void SetNetworkName(const NameData &aNetworkNameData)
320         {
321             IgnoreError(AsCoreType(&mNetworkName).Set(aNetworkNameData));
322             mComponents.mIsNetworkNamePresent = true;
323         }
324 
325         /**
326          * This method indicates whether or not the Extended PAN ID is present in the Dataset.
327          *
328          * @returns TRUE if Extended PAN ID is present, FALSE otherwise.
329          *
330          */
IsExtendedPanIdPresent(void) const331         bool IsExtendedPanIdPresent(void) const { return mComponents.mIsExtendedPanIdPresent; }
332 
333         /**
334          * This method gets the Extended PAN ID in the Dataset.
335          *
336          * This method MUST be used when Extended PAN ID component is present in the Dataset, otherwise its behavior is
337          * undefined.
338          *
339          * @returns The Extended PAN ID in the Dataset.
340          *
341          */
GetExtendedPanId(void) const342         const ExtendedPanId &GetExtendedPanId(void) const { return AsCoreType(&mExtendedPanId); }
343 
344         /**
345          * This method sets the Extended PAN ID in the Dataset.
346          *
347          * @param[in] aExtendedPanId   An Extended PAN ID.
348          *
349          */
SetExtendedPanId(const ExtendedPanId & aExtendedPanId)350         void SetExtendedPanId(const ExtendedPanId &aExtendedPanId)
351         {
352             mExtendedPanId                      = aExtendedPanId;
353             mComponents.mIsExtendedPanIdPresent = true;
354         }
355 
356         /**
357          * This method indicates whether or not the Mesh Local Prefix is present in the Dataset.
358          *
359          * @returns TRUE if Mesh Local Prefix is present, FALSE otherwise.
360          *
361          */
IsMeshLocalPrefixPresent(void) const362         bool IsMeshLocalPrefixPresent(void) const { return mComponents.mIsMeshLocalPrefixPresent; }
363 
364         /**
365          * This method gets the Mesh Local Prefix in the Dataset.
366          *
367          * This method MUST be used when Mesh Local Prefix component is present in the Dataset, otherwise its behavior
368          * is undefined.
369          *
370          * @returns The Mesh Local Prefix in the Dataset.
371          *
372          */
GetMeshLocalPrefix(void) const373         const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const
374         {
375             return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix);
376         }
377 
378         /**
379          * This method sets the Mesh Local Prefix in the Dataset.
380          *
381          * @param[in] aMeshLocalPrefix   A Mesh Local Prefix.
382          *
383          */
SetMeshLocalPrefix(const Ip6::NetworkPrefix & aMeshLocalPrefix)384         void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix)
385         {
386             mMeshLocalPrefix                      = aMeshLocalPrefix;
387             mComponents.mIsMeshLocalPrefixPresent = true;
388         }
389 
390         /**
391          * This method indicates whether or not the Delay Timer is present in the Dataset.
392          *
393          * @returns TRUE if Delay Timer is present, FALSE otherwise.
394          *
395          */
IsDelayPresent(void) const396         bool IsDelayPresent(void) const { return mComponents.mIsDelayPresent; }
397 
398         /**
399          * This method gets the Delay Timer in the Dataset.
400          *
401          * This method MUST be used when Delay Timer component is present in the Dataset, otherwise its behavior is
402          * undefined.
403          *
404          * @returns The Delay Timer in the Dataset.
405          *
406          */
GetDelay(void) const407         uint32_t GetDelay(void) const { return mDelay; }
408 
409         /**
410          * This method sets the Delay Timer in the Dataset.
411          *
412          * @param[in] aDelay  A Delay value.
413          *
414          */
SetDelay(uint32_t aDelay)415         void SetDelay(uint32_t aDelay)
416         {
417             mDelay                      = aDelay;
418             mComponents.mIsDelayPresent = true;
419         }
420 
421         /**
422          * This method indicates whether or not the PAN ID is present in the Dataset.
423          *
424          * @returns TRUE if PAN ID is present, FALSE otherwise.
425          *
426          */
IsPanIdPresent(void) const427         bool IsPanIdPresent(void) const { return mComponents.mIsPanIdPresent; }
428 
429         /**
430          * This method gets the PAN ID in the Dataset.
431          *
432          * This method MUST be used when PAN ID component is present in the Dataset, otherwise its behavior is
433          * undefined.
434          *
435          * @returns The PAN ID in the Dataset.
436          *
437          */
GetPanId(void) const438         Mac::PanId GetPanId(void) const { return mPanId; }
439 
440         /**
441          * This method sets the PAN ID in the Dataset.
442          *
443          * @param[in] aPanId  A PAN ID.
444          *
445          */
SetPanId(Mac::PanId aPanId)446         void SetPanId(Mac::PanId aPanId)
447         {
448             mPanId                      = aPanId;
449             mComponents.mIsPanIdPresent = true;
450         }
451 
452         /**
453          * This method indicates whether or not the Channel is present in the Dataset.
454          *
455          * @returns TRUE if Channel is present, FALSE otherwise.
456          *
457          */
IsChannelPresent(void) const458         bool IsChannelPresent(void) const { return mComponents.mIsChannelPresent; }
459 
460         /**
461          * This method gets the Channel in the Dataset.
462          *
463          * This method MUST be used when Channel component is present in the Dataset, otherwise its behavior is
464          * undefined.
465          *
466          * @returns The Channel in the Dataset.
467          *
468          */
GetChannel(void) const469         uint16_t GetChannel(void) const { return mChannel; }
470 
471         /**
472          * This method sets the Channel in the Dataset.
473          *
474          * @param[in] aChannel  A Channel.
475          *
476          */
SetChannel(uint16_t aChannel)477         void SetChannel(uint16_t aChannel)
478         {
479             mChannel                      = aChannel;
480             mComponents.mIsChannelPresent = true;
481         }
482 
483         /**
484          * This method indicates whether or not the PSKc is present in the Dataset.
485          *
486          * @returns TRUE if PSKc is present, FALSE otherwise.
487          *
488          */
IsPskcPresent(void) const489         bool IsPskcPresent(void) const { return mComponents.mIsPskcPresent; }
490 
491         /**
492          * This method gets the PSKc in the Dataset.
493          *
494          * This method MUST be used when PSKc component is present in the Dataset, otherwise its behavior is undefined.
495          *
496          * @returns The PSKc in the Dataset.
497          *
498          */
GetPskc(void) const499         const Pskc &GetPskc(void) const { return AsCoreType(&mPskc); }
500 
501         /**
502          * This method set the PSKc in the Dataset.
503          *
504          * @param[in] aPskc  A PSKc value.
505          *
506          */
SetPskc(const Pskc & aPskc)507         void SetPskc(const Pskc &aPskc)
508         {
509             mPskc                      = aPskc;
510             mComponents.mIsPskcPresent = true;
511         }
512 
513         /**
514          * This method indicates whether or not the Security Policy is present in the Dataset.
515          *
516          * @returns TRUE if Security Policy is present, FALSE otherwise.
517          *
518          */
IsSecurityPolicyPresent(void) const519         bool IsSecurityPolicyPresent(void) const { return mComponents.mIsSecurityPolicyPresent; }
520 
521         /**
522          * This method gets the Security Policy in the Dataset.
523          *
524          * This method MUST be used when Security Policy component is present in the Dataset, otherwise its behavior is
525          * undefined.
526          *
527          * @returns The Security Policy in the Dataset.
528          *
529          */
GetSecurityPolicy(void) const530         const SecurityPolicy &GetSecurityPolicy(void) const { return AsCoreType(&mSecurityPolicy); }
531 
532         /**
533          * This method sets the Security Policy in the Dataset.
534          *
535          * @param[in] aSecurityPolicy  A Security Policy to set in Dataset.
536          *
537          */
SetSecurityPolicy(const SecurityPolicy & aSecurityPolicy)538         void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
539         {
540             mSecurityPolicy                      = aSecurityPolicy;
541             mComponents.mIsSecurityPolicyPresent = true;
542         }
543 
544         /**
545          * This method indicates whether or not the Channel Mask is present in the Dataset.
546          *
547          * @returns TRUE if Channel Mask is present, FALSE otherwise.
548          *
549          */
IsChannelMaskPresent(void) const550         bool IsChannelMaskPresent(void) const { return mComponents.mIsChannelMaskPresent; }
551 
552         /**
553          * This method gets the Channel Mask in the Dataset.
554          *
555          * This method MUST be used when Channel Mask component is present in the Dataset, otherwise its behavior is
556          * undefined.
557          *
558          * @returns The Channel Mask in the Dataset.
559          *
560          */
GetChannelMask(void) const561         otChannelMask GetChannelMask(void) const { return mChannelMask; }
562 
563         /**
564          * This method sets the Channel Mask in the Dataset.
565          *
566          * @param[in] aChannelMask   A Channel Mask value.
567          *
568          */
SetChannelMask(otChannelMask aChannelMask)569         void SetChannelMask(otChannelMask aChannelMask)
570         {
571             mChannelMask                      = aChannelMask;
572             mComponents.mIsChannelMaskPresent = true;
573         }
574 
575         /**
576          * This method populates the Dataset with random fields.
577          *
578          * The Network Key, PSKc, Mesh Local Prefix, PAN ID, and Extended PAN ID are generated randomly (crypto-secure)
579          * with Network Name set to "OpenThread-%04x" with PAN ID appended as hex. The Channel is chosen randomly from
580          * radio's preferred channel mask, Channel Mask is set from radio's supported mask, and Security Policy Flags
581          * from current `KeyManager` value.
582          *
583          * @param[in] aInstance    The OpenThread instance.
584          *
585          * @retval kErrorNone If the Dataset was generated successfully.
586          *
587          */
588         Error GenerateRandom(Instance &aInstance);
589 
590         /**
591          * This method checks whether the Dataset is a subset of another one, i.e., all the components in the current
592          * Dataset are also present in the @p aOther and the component values fully match.
593          *
594          * The matching of components in the two Datasets excludes Active/Pending Timestamp and Delay components.
595          *
596          * @param[in] aOther   The other Dataset to check against.
597          *
598          * @retval TRUE   The current dataset is a subset of @p aOther.
599          * @retval FALSE  The current Dataset is not a subset of @p aOther.
600          *
601          */
602         bool IsSubsetOf(const Info &aOther) const;
603     };
604 
605     /**
606      * This constructor initializes the object.
607      *
608      */
609     Dataset(void);
610 
611     /**
612      * This method clears the Dataset.
613      *
614      */
615     void Clear(void);
616 
617     /**
618      * This method indicates whether or not the dataset appears to be well-formed.
619      *
620      * @returns TRUE if the dataset appears to be well-formed, FALSE otherwise.
621      *
622      */
623     bool IsValid(void) const;
624 
625     /**
626      * This method returns a pointer to the TLV with a given type.
627      *
628      * @param[in] aType  A TLV type.
629      *
630      * @returns A pointer to the TLV or `nullptr` if none is found.
631      *
632      */
GetTlv(Tlv::Type aType)633     Tlv *GetTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->GetTlv(aType)); }
634 
635     /**
636      * This method returns a pointer to the TLV with a given type.
637      *
638      * @param[in] aType  The TLV type.
639      *
640      * @returns A pointer to the TLV or `nullptr` if none is found.
641      *
642      */
643     const Tlv *GetTlv(Tlv::Type aType) const;
644 
645     /**
646      * This template method returns a pointer to the TLV with a given template type `TlvType`
647      *
648      * @returns A pointer to the TLV or `nullptr` if none is found.
649      *
650      */
GetTlv(void)651     template <typename TlvType> TlvType *GetTlv(void)
652     {
653         return As<TlvType>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
654     }
655 
656     /**
657      * This template method returns a pointer to the TLV with a given template type `TlvType`
658      *
659      * @returns A pointer to the TLV or `nullptr` if none is found.
660      *
661      */
GetTlv(void) const662     template <typename TlvType> const TlvType *GetTlv(void) const
663     {
664         return As<TlvType>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
665     }
666 
667     /**
668      * This method returns a pointer to the byte representation of the Dataset.
669      *
670      * @returns A pointer to the byte representation of the Dataset.
671      *
672      */
GetBytes(void)673     uint8_t *GetBytes(void) { return mTlvs; }
674 
675     /**
676      * This method returns a pointer to the byte representation of the Dataset.
677      *
678      * @returns A pointer to the byte representation of the Dataset.
679      *
680      */
GetBytes(void) const681     const uint8_t *GetBytes(void) const { return mTlvs; }
682 
683     /**
684      * This method converts the TLV representation to structure representation.
685      *
686      * @param[out] aDatasetInfo  A reference to `Info` object to output the Dataset.
687      *
688      */
689     void ConvertTo(Info &aDatasetInfo) const;
690 
691     /**
692      * This method converts the TLV representation to structure representation.
693      *
694      * @param[out] aDataset  A reference to `otOperationalDatasetTlvs` to output the Dataset.
695      *
696      */
697     void ConvertTo(otOperationalDatasetTlvs &aDataset) const;
698 
699     /**
700      * This method returns the Dataset size in bytes.
701      *
702      * @returns The Dataset size in bytes.
703      *
704      */
GetSize(void) const705     uint16_t GetSize(void) const { return mLength; }
706 
707     /**
708      * This method sets the Dataset size in bytes.
709      *
710      * @param[in] aSize  The Dataset size in bytes.
711      *
712      */
SetSize(uint16_t aSize)713     void SetSize(uint16_t aSize) { mLength = aSize; }
714 
715     /**
716      * This method returns the local time the dataset was last updated.
717      *
718      * @returns The local time the dataset was last updated.
719      *
720      */
GetUpdateTime(void) const721     TimeMilli GetUpdateTime(void) const { return mUpdateTime; }
722 
723     /**
724      * This method gets the Timestamp (Active or Pending).
725      *
726      * @param[in]  aType       The type: active or pending.
727      * @param[out] aTimestamp  A reference to a `Timestamp` to output the value.
728      *
729      * @retval kErrorNone      Timestamp was read successfully. @p aTimestamp is updated.
730      * @retval kErrorNotFound  Could not find the requested Timestamp TLV.
731      *
732      */
733     Error GetTimestamp(Type aType, Timestamp &aTimestamp) const;
734 
735     /**
736      * This method sets the Timestamp value.
737      *
738      * @param[in] aType        The type: active or pending.
739      * @param[in] aTimestamp   A Timestamp.
740      *
741      */
742     void SetTimestamp(Type aType, const Timestamp &aTimestamp);
743 
744     /**
745      * This method sets a TLV in the Dataset.
746      *
747      * @param[in]  aTlv  A reference to the TLV.
748      *
749      * @retval kErrorNone    Successfully set the TLV.
750      * @retval kErrorNoBufs  Could not set the TLV due to insufficient buffer space.
751      *
752      */
753     Error SetTlv(const Tlv &aTlv);
754 
755     /**
756      * This method sets a TLV with a given TLV Type and Value.
757      *
758      * @param[in] aType     The TLV Type.
759      * @param[in] aValue    A pointer to TLV Value.
760      * @param[in] aLength   The TLV Length in bytes (length of @p aValue).
761      *
762      * @retval kErrorNone    Successfully set the TLV.
763      * @retval kErrorNoBufs  Could not set the TLV due to insufficient buffer space.
764      *
765      */
766     Error SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
767 
768     /**
769      * This template method sets a TLV with a given TLV Type and Value.
770      *
771      * @tparam ValueType    The type of TLV's Value.
772      *
773      * @param[in] aType     The TLV Type.
774      * @param[in] aValue    The TLV Value (of type `ValueType`).
775      *
776      * @retval kErrorNone    Successfully set the TLV.
777      * @retval kErrorNoBufs  Could not set the TLV due to insufficient buffer space.
778      *
779      */
SetTlv(Tlv::Type aType,const ValueType & aValue)780     template <typename ValueType> Error SetTlv(Tlv::Type aType, const ValueType &aValue)
781     {
782         static_assert(!TypeTraits::IsPointer<ValueType>::kValue, "ValueType must not be a pointer");
783 
784         return SetTlv(aType, &aValue, sizeof(ValueType));
785     }
786 
787     /**
788      * This method reads the Dataset from a given message and checks that it is well-formed and valid.
789      *
790      * @param[in]  aMessage  The message to read from.
791      * @param[in]  aOffset   The offset in @p aMessage to start reading the Dataset TLVs.
792      * @param[in]  aLength   The dataset length in bytes.
793      *
794      * @retval kErrorNone    Successfully read and validated the Dataset.
795      * @retval kErrorParse   Could not read or parse the dataset from @p aMessage.
796      *
797      */
798     Error ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
799 
800     /**
801      * This method sets the Dataset using an existing Dataset.
802      *
803      * If this Dataset is an Active Dataset, any Pending Timestamp and Delay Timer TLVs will be omitted in the copy
804      * from @p aDataset.
805      *
806      * @param[in]  aType     The type of the dataset, active or pending.
807      * @param[in]  aDataset  The input Dataset.
808      *
809      */
810     void Set(Type aType, const Dataset &aDataset);
811 
812     /**
813      * This method sets the Dataset from a given structure representation.
814      *
815      * @param[in]  aDatasetInfo  The input Dataset as `Dataset::Info`.
816      *
817      * @retval kErrorNone         Successfully set the Dataset.
818      * @retval kErrorInvalidArgs  Dataset is missing Active and/or Pending Timestamp.
819      *
820      */
821     Error SetFrom(const Info &aDatasetInfo);
822 
823     /**
824      * This method sets the Dataset using @p aDataset.
825      *
826      * @param[in]  aDataset  The input Dataset as otOperationalDatasetTlvs.
827      *
828      */
829     void SetFrom(const otOperationalDatasetTlvs &aDataset);
830 
831     /**
832      * This method removes a TLV from the Dataset.
833      *
834      * @param[in] aType The type of a specific TLV.
835      *
836      */
837     void RemoveTlv(Tlv::Type aType);
838 
839     /**
840      * This method appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV.
841      *
842      * @param[in] aType          The type of the dataset, active or pending.
843      * @param[in] aMessage       A message to append to.
844      *
845      * @retval kErrorNone    Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
846      * @retval kErrorNoBufs  Insufficient available buffers to append the message with MLE Dataset TLV.
847      *
848      */
849     Error AppendMleDatasetTlv(Type aType, Message &aMessage) const;
850 
851     /**
852      * This method applies the Active or Pending Dataset to the Thread interface.
853      *
854      * @param[in]  aInstance            A reference to the OpenThread instance.
855      * @param[out] aIsNetworkKeyUpdated A pointer to where to place whether network key was updated.
856      *
857      * @retval kErrorNone   Successfully applied configuration.
858      * @retval kErrorParse  The dataset has at least one TLV with invalid format.
859      *
860      */
861     Error ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdated = nullptr) const;
862 
863     /**
864      * This method converts a Pending Dataset to an Active Dataset.
865      *
866      * This method removes the Delay Timer and Pending Timestamp TLVs
867      *
868      */
869     void ConvertToActive(void);
870 
871     /**
872      * This method returns a pointer to the start of Dataset TLVs sequence.
873      *
874      * @return  A pointer to the start of Dataset TLVs sequence.
875      *
876      */
GetTlvsStart(void)877     Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); }
878 
879     /**
880      * This method returns a pointer to the start of Dataset TLVs sequence.
881      *
882      * @return  A pointer to start of Dataset TLVs sequence.
883      *
884      */
GetTlvsStart(void) const885     const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); }
886 
887     /**
888      * This method returns a pointer to the past-the-end of Dataset TLVs sequence.
889      *
890      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
891      *
892      * @return  A pointer to past-the-end of Dataset TLVs sequence.
893      *
894      */
GetTlvsEnd(void)895     Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); }
896 
897     /**
898      * This method returns a pointer to the past-the-end of Dataset TLVs sequence.
899      *
900      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
901      *
902      * @return  A pointer to past-the-end of Dataset TLVs sequence.
903      *
904      */
GetTlvsEnd(void) const905     const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); }
906 
907     /**
908      * This static method converts a Dataset Type to a string.
909      *
910      * @param[in]  aType   A Dataset type.
911      *
912      */
913     static const char *TypeToString(Type aType);
914 
915 private:
916     void RemoveTlv(Tlv *aTlv);
917 
918     uint8_t   mTlvs[kMaxSize]; ///< The Dataset buffer
919     TimeMilli mUpdateTime;     ///< Local time last updated
920     uint16_t  mLength;         ///< The number of valid bytes in @var mTlvs
921 };
922 
923 /**
924  * This is a template specialization of `SetTlv<ValueType>` with a `uint16_t` value type.
925  *
926  * @param[in] aType     The TLV Type.
927  * @param[in] aValue    The TLV value (as `uint16_t`).
928  *
929  * @retval kErrorNone    Successfully set the TLV.
930  * @retval kErrorNoBufs  Could not set the TLV due to insufficient buffer space.
931  *
932  */
SetTlv(Tlv::Type aType,const uint16_t & aValue)933 template <> inline Error Dataset::SetTlv(Tlv::Type aType, const uint16_t &aValue)
934 {
935     uint16_t value = Encoding::BigEndian::HostSwap16(aValue);
936 
937     return SetTlv(aType, &value, sizeof(uint16_t));
938 }
939 
940 /**
941  * This is a template specialization of `SetTlv<ValueType>` with a `uint32_t` value type
942  *
943  * @param[in] aType     The TLV Type.
944  * @param[in] aValue    The TLV value (as `uint32_t`).
945  *
946  * @retval kErrorNone    Successfully set the TLV.
947  * @retval kErrorNoBufs  Could not set the TLV due to insufficient buffer space.
948  *
949  */
SetTlv(Tlv::Type aType,const uint32_t & aValue)950 template <> inline Error Dataset::SetTlv(Tlv::Type aType, const uint32_t &aValue)
951 {
952     uint32_t value = Encoding::BigEndian::HostSwap32(aValue);
953 
954     return SetTlv(aType, &value, sizeof(uint32_t));
955 }
956 
957 } // namespace MeshCoP
958 
959 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
960 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
961 
962 } // namespace ot
963 
964 #endif // MESHCOP_DATASET_HPP_
965