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