1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for managing MeshCoP Datasets.
32  *
33  */
34 
35 #ifndef MESHCOP_DATASET_HPP_
36 #define MESHCOP_DATASET_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include <openthread/dataset.h>
41 
42 #include "common/as_core_type.hpp"
43 #include "common/clearable.hpp"
44 #include "common/const_cast.hpp"
45 #include "common/locator.hpp"
46 #include "common/message.hpp"
47 #include "common/timer.hpp"
48 #include "common/type_traits.hpp"
49 #include "meshcop/meshcop_tlvs.hpp"
50 #include "thread/mle_types.hpp"
51 
52 namespace ot {
53 namespace MeshCoP {
54 
55 /**
56  * Represents MeshCop Dataset.
57  *
58  */
59 class Dataset
60 {
61     friend class 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      * 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      * 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          * 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          * 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          * 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          * 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          * 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          * 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          * 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          * 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          * 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          * 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          * 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          * 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      * 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          * 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          * Gets the Active Timestamp in the Dataset.
199          *
200          * MUST be used when Active Timestamp component is present in the Dataset, otherwise its behavior is
201          * undefined.
202          *
203          * @param[out] aTimestamp  A reference to output the Active Timestamp in the Dataset.
204          *
205          */
GetActiveTimestamp(Timestamp & aTimestamp) const206         void GetActiveTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mActiveTimestamp); }
207 
208         /**
209          * 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          * 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          * Gets the Pending Timestamp in the Dataset.
230          *
231          * MUST be used when Pending Timestamp component is present in the Dataset, otherwise its behavior
232          * is undefined.
233          *
234          * @param[out] aTimestamp  A reference to output the Pending Timestamp in the Dataset.
235          *
236          */
GetPendingTimestamp(Timestamp & aTimestamp) const237         void GetPendingTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mPendingTimestamp); }
238 
239         /**
240          * 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          * 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          * Gets the Network Key in the Dataset.
261          *
262          * 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          * 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          * 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          * 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          * Gets the Network Name in the Dataset.
304          *
305          * 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          * 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          * 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          * Gets the Extended PAN ID in the Dataset.
335          *
336          * 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          * 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          * 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          * Gets the Mesh Local Prefix in the Dataset.
366          *
367          * 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          * 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          * 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          * Gets the Delay Timer in the Dataset.
400          *
401          * 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          * 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          * 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          * Gets the PAN ID in the Dataset.
431          *
432          * 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          * 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          * 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          * Gets the Channel in the Dataset.
462          *
463          * 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          * 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          * 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          * Gets the PSKc in the Dataset.
493          *
494          * 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          * 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          * 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          * Gets the Security Policy in the Dataset.
523          *
524          * 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          * 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          * 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          * Gets the Channel Mask in the Dataset.
554          *
555          * 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          * 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          * 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          * 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      * Initializes the object.
607      *
608      */
609     Dataset(void);
610 
611     /**
612      * Clears the Dataset.
613      *
614      */
615     void Clear(void);
616 
617     /**
618      * 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      * Indicates whether or not a given TLV type is present in the Dataset.
627      *
628      * @param[in] aType  The TLV type to check.
629      *
630      * @retval TRUE    TLV with @p aType is present in the Dataset.
631      * @retval FALSE   TLV with @p aType is not present in the Dataset.
632      *
633      */
ContainsTlv(Tlv::Type aType) const634     bool ContainsTlv(Tlv::Type aType) const { return (FindTlv(aType) != nullptr); }
635 
636     /**
637      * Indicates whether or not a given TLV type is present in the Dataset.
638      *
639      * @tparam  aTlvType  The TLV type to check.
640      *
641      * @retval TRUE    TLV of @p aTlvType is present in the Dataset.
642      * @retval FALSE   TLV of @p aTlvType is not present in the Dataset.
643      *
644      */
Contains(void) const645     template <typename TlvType> bool Contains(void) const
646     {
647         return ContainsTlv(static_cast<Tlv::Type>(TlvType::kType));
648     }
649 
650     /**
651      * Searches for a given TLV type in the Dataset.
652      *
653      * @param[in] aType  The TLV type to find.
654      *
655      * @returns A pointer to the TLV or `nullptr` if not found.
656      *
657      */
FindTlv(Tlv::Type aType)658     Tlv *FindTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->FindTlv(aType)); }
659 
660     /**
661      * Searches for a given TLV type in the Dataset.
662      *
663      * @param[in] aType  The TLV type to find.
664      *
665      * @returns A pointer to the TLV or `nullptr` if not found.
666      *
667      */
668     const Tlv *FindTlv(Tlv::Type aType) const;
669 
670     /**
671      * Writes a TLV to the Dataset.
672      *
673      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
674      *
675      * @param[in] aTlv     A reference to the TLV.
676      *
677      * @retval kErrorNone    Successfully updated the TLV.
678      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
679      *
680      */
681     Error WriteTlv(const Tlv &aTlv);
682 
683     /**
684      * Writes a TLV in the Dataset.
685      *
686      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
687      *
688      * @param[in]  aType     The TLV type.
689      * @param[in]  aValue    A pointer to a buffer containing the TLV value.
690      * @param[in]  aLength   The TLV length.
691      *
692      * @retval kErrorNone    Successfully updated the TLV.
693      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
694      *
695      */
696     Error WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
697 
698     /**
699      * Writes a simple TLV in the Dataset.
700      *
701      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
702      *
703      * @tparam  SimpleTlvType   The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
704      *
705      * @param[in] aValue   The TLV value.
706      *
707      * @retval kErrorNone    Successfully updated the TLV.
708      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
709      *
710      */
Write(const typename SimpleTlvType::ValueType & aValue)711     template <typename SimpleTlvType> Error Write(const typename SimpleTlvType::ValueType &aValue)
712     {
713         return WriteTlv(static_cast<Tlv::Type>(SimpleTlvType::kType), &aValue, sizeof(aValue));
714     }
715 
716     /**
717      * Writes a `uint` TLV in the Dataset.
718      *
719      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
720      *
721      * @tparam  UintTlvType     The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
722      *
723      * @param[in]  aValue   The TLV value.
724      *
725      * @retval kErrorNone    Successfully updated the TLV.
726      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
727      *
728      */
Write(typename UintTlvType::UintValueType aValue)729     template <typename UintTlvType> Error Write(typename UintTlvType::UintValueType aValue)
730     {
731         typename UintTlvType::UintValueType value = BigEndian::HostSwap(aValue);
732 
733         return WriteTlv(static_cast<Tlv::Type>(UintTlvType::kType), &value, sizeof(value));
734     }
735 
736     /**
737      * Removes a TLV from the Dataset.
738      *
739      * If the Dataset does not contain the given TLV type, no action is performed.
740      *
741      * @param[in] aType  The TLV type to remove.
742      *
743      */
744     void RemoveTlv(Tlv::Type aType);
745 
746     /**
747      * Returns a pointer to the byte representation of the Dataset.
748      *
749      * @returns A pointer to the byte representation of the Dataset.
750      *
751      */
GetBytes(void)752     uint8_t *GetBytes(void) { return mTlvs; }
753 
754     /**
755      * Returns a pointer to the byte representation of the Dataset.
756      *
757      * @returns A pointer to the byte representation of the Dataset.
758      *
759      */
GetBytes(void) const760     const uint8_t *GetBytes(void) const { return mTlvs; }
761 
762     /**
763      * Converts the TLV representation to structure representation.
764      *
765      * @param[out] aDatasetInfo  A reference to `Info` object to output the Dataset.
766      *
767      */
768     void ConvertTo(Info &aDatasetInfo) const;
769 
770     /**
771      * Converts the TLV representation to structure representation.
772      *
773      * @param[out] aDataset  A reference to `otOperationalDatasetTlvs` to output the Dataset.
774      *
775      */
776     void ConvertTo(otOperationalDatasetTlvs &aDataset) const;
777 
778     /**
779      * Returns the Dataset size in bytes.
780      *
781      * @returns The Dataset size in bytes.
782      *
783      */
GetSize(void) const784     uint16_t GetSize(void) const { return mLength; }
785 
786     /**
787      * Sets the Dataset size in bytes.
788      *
789      * @param[in] aSize  The Dataset size in bytes.
790      *
791      */
SetSize(uint16_t aSize)792     void SetSize(uint16_t aSize) { mLength = aSize; }
793 
794     /**
795      * Returns the local time the dataset was last updated.
796      *
797      * @returns The local time the dataset was last updated.
798      *
799      */
GetUpdateTime(void) const800     TimeMilli GetUpdateTime(void) const { return mUpdateTime; }
801 
802     /**
803      * Gets the Timestamp (Active or Pending).
804      *
805      * @param[in]  aType       The type: active or pending.
806      * @param[out] aTimestamp  A reference to a `Timestamp` to output the value.
807      *
808      * @retval kErrorNone      Timestamp was read successfully. @p aTimestamp is updated.
809      * @retval kErrorNotFound  Could not find the requested Timestamp TLV.
810      *
811      */
812     Error GetTimestamp(Type aType, Timestamp &aTimestamp) const;
813 
814     /**
815      * Sets the Timestamp value.
816      *
817      * @param[in] aType        The type: active or pending.
818      * @param[in] aTimestamp   A Timestamp.
819      *
820      */
821     void SetTimestamp(Type aType, const Timestamp &aTimestamp);
822 
823     /**
824      * Reads the Dataset from a given message and checks that it is well-formed and valid.
825      *
826      * @param[in]  aMessage  The message to read from.
827      * @param[in]  aOffset   The offset in @p aMessage to start reading the Dataset TLVs.
828      * @param[in]  aLength   The dataset length in bytes.
829      *
830      * @retval kErrorNone    Successfully read and validated the Dataset.
831      * @retval kErrorParse   Could not read or parse the dataset from @p aMessage.
832      *
833      */
834     Error ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
835 
836     /**
837      * Sets the Dataset using an existing Dataset.
838      *
839      * If this Dataset is an Active Dataset, any Pending Timestamp and Delay Timer TLVs will be omitted in the copy
840      * from @p aDataset.
841      *
842      * @param[in]  aType     The type of the dataset, active or pending.
843      * @param[in]  aDataset  The input Dataset.
844      *
845      */
846     void Set(Type aType, const Dataset &aDataset);
847 
848     /**
849      * Sets the Dataset from a given structure representation.
850      *
851      * @param[in]  aDatasetInfo  The input Dataset as `Dataset::Info`.
852      *
853      * @retval kErrorNone         Successfully set the Dataset.
854      * @retval kErrorInvalidArgs  Dataset is missing Active and/or Pending Timestamp.
855      *
856      */
857     Error SetFrom(const Info &aDatasetInfo);
858 
859     /**
860      * Sets the Dataset using @p aDataset.
861      *
862      * @param[in]  aDataset  The input Dataset as otOperationalDatasetTlvs.
863      *
864      */
865     void SetFrom(const otOperationalDatasetTlvs &aDataset);
866 
867     /**
868      * Appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV.
869      *
870      * @param[in] aType          The type of the dataset, active or pending.
871      * @param[in] aMessage       A message to append to.
872      *
873      * @retval kErrorNone    Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
874      * @retval kErrorNoBufs  Insufficient available buffers to append the message with MLE Dataset TLV.
875      *
876      */
877     Error AppendMleDatasetTlv(Type aType, Message &aMessage) const;
878 
879     /**
880      * Applies the Active or Pending Dataset to the Thread interface.
881      *
882      * @param[in]  aInstance            A reference to the OpenThread instance.
883      * @param[out] aIsNetworkKeyUpdated A pointer to where to place whether network key was updated.
884      *
885      * @retval kErrorNone   Successfully applied configuration.
886      * @retval kErrorParse  The dataset has at least one TLV with invalid format.
887      *
888      */
889     Error ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdated = nullptr) const;
890 
891     /**
892      * Converts a Pending Dataset to an Active Dataset.
893      *
894      * Removes the Delay Timer and Pending Timestamp TLVs
895      *
896      */
897     void ConvertToActive(void);
898 
899     /**
900      * Returns a pointer to the start of Dataset TLVs sequence.
901      *
902      * @return  A pointer to the start of Dataset TLVs sequence.
903      *
904      */
GetTlvsStart(void)905     Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); }
906 
907     /**
908      * Returns a pointer to the start of Dataset TLVs sequence.
909      *
910      * @return  A pointer to start of Dataset TLVs sequence.
911      *
912      */
GetTlvsStart(void) const913     const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); }
914 
915     /**
916      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
917      *
918      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
919      *
920      * @return  A pointer to past-the-end of Dataset TLVs sequence.
921      *
922      */
GetTlvsEnd(void)923     Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); }
924 
925     /**
926      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
927      *
928      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
929      *
930      * @return  A pointer to past-the-end of Dataset TLVs sequence.
931      *
932      */
GetTlvsEnd(void) const933     const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); }
934 
935     /**
936      * Converts a Dataset Type to a string.
937      *
938      * @param[in]  aType   A Dataset type.
939      *
940      */
941     static const char *TypeToString(Type aType);
942 
943 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
944 
945     /**
946      * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero.
947      *
948      * If the Dataset does not contain the @p aTlvType, no action is performed.
949      *
950      * @param[in] aTlvType    The TLV type.
951      * @param[in] aKeyRef     The `KeyRef` to use with secure storage.
952      *
953      */
954     void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
955 
956     /**
957      * Reads and updates a given TLV value in Dataset from secure storage.
958      *
959      * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned.
960      *
961      * @param[in] aTlvType    The TLV type.
962      * @param[in] aKeyRef     The `KeyRef` to use with secure storage.
963      *
964      * @retval kErrorNone    Successfully read the TLV value from secure storage and updated the Dataset.
965      * @retval KErrorFailed  Could not read the @aKeyRef from secure storage.
966      *
967      */
968     Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
969 
970 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
971 
972 private:
973     void RemoveTlv(Tlv *aTlv);
974 
975     uint8_t   mTlvs[kMaxSize]; ///< The Dataset buffer
976     TimeMilli mUpdateTime;     ///< Local time last updated
977     uint16_t  mLength;         ///< The number of valid bytes in @var mTlvs
978 };
979 
980 } // namespace MeshCoP
981 
982 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
983 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
984 
985 } // namespace ot
986 
987 #endif // MESHCOP_DATASET_HPP_
988