• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 a Dataset as a sequence of TLVs.
80      *
81      */
82     typedef otOperationalDatasetTlvs Tlvs;
83 
84     /**
85      * Represents presence of different components in Active or Pending Operational Dataset.
86      *
87      */
88     class Components : public otOperationalDatasetComponents, public Clearable<Components>
89     {
90     public:
91         /**
92          * Indicates whether or not the Active Timestamp is present in the Dataset.
93          *
94          * @returns TRUE if Active Timestamp is present, FALSE otherwise.
95          *
96          */
IsActiveTimestampPresent(void) const97         bool IsActiveTimestampPresent(void) const { return mIsActiveTimestampPresent; }
98 
99         /**
100          * Indicates whether or not the Pending Timestamp is present in the Dataset.
101          *
102          * @returns TRUE if Pending Timestamp is present, FALSE otherwise.
103          *
104          */
IsPendingTimestampPresent(void) const105         bool IsPendingTimestampPresent(void) const { return mIsPendingTimestampPresent; }
106 
107         /**
108          * Indicates whether or not the Network Key is present in the Dataset.
109          *
110          * @returns TRUE if Network Key is present, FALSE otherwise.
111          *
112          */
IsNetworkKeyPresent(void) const113         bool IsNetworkKeyPresent(void) const { return mIsNetworkKeyPresent; }
114 
115         /**
116          * Indicates whether or not the Network Name is present in the Dataset.
117          *
118          * @returns TRUE if Network Name is present, FALSE otherwise.
119          *
120          */
IsNetworkNamePresent(void) const121         bool IsNetworkNamePresent(void) const { return mIsNetworkNamePresent; }
122 
123         /**
124          * Indicates whether or not the Extended PAN ID is present in the Dataset.
125          *
126          * @returns TRUE if Extended PAN ID is present, FALSE otherwise.
127          *
128          */
IsExtendedPanIdPresent(void) const129         bool IsExtendedPanIdPresent(void) const { return mIsExtendedPanIdPresent; }
130 
131         /**
132          * Indicates whether or not the Mesh Local Prefix is present in the Dataset.
133          *
134          * @returns TRUE if Mesh Local Prefix is present, FALSE otherwise.
135          *
136          */
IsMeshLocalPrefixPresent(void) const137         bool IsMeshLocalPrefixPresent(void) const { return mIsMeshLocalPrefixPresent; }
138 
139         /**
140          * Indicates whether or not the Delay Timer is present in the Dataset.
141          *
142          * @returns TRUE if Delay Timer is present, FALSE otherwise.
143          *
144          */
IsDelayPresent(void) const145         bool IsDelayPresent(void) const { return mIsDelayPresent; }
146 
147         /**
148          * Indicates whether or not the PAN ID is present in the Dataset.
149          *
150          * @returns TRUE if PAN ID is present, FALSE otherwise.
151          *
152          */
IsPanIdPresent(void) const153         bool IsPanIdPresent(void) const { return mIsPanIdPresent; }
154 
155         /**
156          * Indicates whether or not the Channel is present in the Dataset.
157          *
158          * @returns TRUE if Channel is present, FALSE otherwise.
159          *
160          */
IsChannelPresent(void) const161         bool IsChannelPresent(void) const { return mIsChannelPresent; }
162 
163         /**
164          * Indicates whether or not the PSKc is present in the Dataset.
165          *
166          * @returns TRUE if PSKc is present, FALSE otherwise.
167          *
168          */
IsPskcPresent(void) const169         bool IsPskcPresent(void) const { return mIsPskcPresent; }
170 
171         /**
172          * Indicates whether or not the Security Policy is present in the Dataset.
173          *
174          * @returns TRUE if Security Policy is present, FALSE otherwise.
175          *
176          */
IsSecurityPolicyPresent(void) const177         bool IsSecurityPolicyPresent(void) const { return mIsSecurityPolicyPresent; }
178 
179         /**
180          * Indicates whether or not the Channel Mask is present in the Dataset.
181          *
182          * @returns TRUE if Channel Mask is present, FALSE otherwise.
183          *
184          */
IsChannelMaskPresent(void) const185         bool IsChannelMaskPresent(void) const { return mIsChannelMaskPresent; }
186     };
187 
188     /**
189      * Represents the information about the fields contained an Active or Pending Operational Dataset.
190      *
191      */
192     class Info : public otOperationalDataset, public Clearable<Info>
193     {
194     public:
195         /**
196          * Indicates whether or not the Active Timestamp is present in the Dataset.
197          *
198          * @returns TRUE if Active Timestamp is present, FALSE otherwise.
199          *
200          */
IsActiveTimestampPresent(void) const201         bool IsActiveTimestampPresent(void) const { return mComponents.mIsActiveTimestampPresent; }
202 
203         /**
204          * Gets the Active Timestamp in the Dataset.
205          *
206          * MUST be used when Active Timestamp component is present in the Dataset, otherwise its behavior is
207          * undefined.
208          *
209          * @param[out] aTimestamp  A reference to output the Active Timestamp in the Dataset.
210          *
211          */
GetActiveTimestamp(Timestamp & aTimestamp) const212         void GetActiveTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mActiveTimestamp); }
213 
214         /**
215          * Sets the Active Timestamp in the Dataset.
216          *
217          * @param[in] aTimestamp   A Timestamp value.
218          *
219          */
SetActiveTimestamp(const Timestamp & aTimestamp)220         void SetActiveTimestamp(const Timestamp &aTimestamp)
221         {
222             aTimestamp.ConvertTo(mActiveTimestamp);
223             mComponents.mIsActiveTimestampPresent = true;
224         }
225 
226         /**
227          * Indicates whether or not the Pending Timestamp is present in the Dataset.
228          *
229          * @returns TRUE if Pending Timestamp is present, FALSE otherwise.
230          *
231          */
IsPendingTimestampPresent(void) const232         bool IsPendingTimestampPresent(void) const { return mComponents.mIsPendingTimestampPresent; }
233 
234         /**
235          * Gets the Pending Timestamp in the Dataset.
236          *
237          * MUST be used when Pending Timestamp component is present in the Dataset, otherwise its behavior
238          * is undefined.
239          *
240          * @param[out] aTimestamp  A reference to output the Pending Timestamp in the Dataset.
241          *
242          */
GetPendingTimestamp(Timestamp & aTimestamp) const243         void GetPendingTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mPendingTimestamp); }
244 
245         /**
246          * Sets the Pending Timestamp in the Dataset.
247          *
248          * @param[in] aTimestamp   A Timestamp value.
249          *
250          */
SetPendingTimestamp(const Timestamp & aTimestamp)251         void SetPendingTimestamp(const Timestamp &aTimestamp)
252         {
253             aTimestamp.ConvertTo(mPendingTimestamp);
254             mComponents.mIsPendingTimestampPresent = true;
255         }
256 
257         /**
258          * Indicates whether or not the Network Key is present in the Dataset.
259          *
260          * @returns TRUE if Network Key is present, FALSE otherwise.
261          *
262          */
IsNetworkKeyPresent(void) const263         bool IsNetworkKeyPresent(void) const { return mComponents.mIsNetworkKeyPresent; }
264 
265         /**
266          * Gets the Network Key in the Dataset.
267          *
268          * MUST be used when Network Key component is present in the Dataset, otherwise its behavior
269          * is undefined.
270          *
271          * @returns The Network Key in the Dataset.
272          *
273          */
GetNetworkKey(void) const274         const NetworkKey &GetNetworkKey(void) const { return AsCoreType(&mNetworkKey); }
275 
276         /**
277          * Sets the Network Key in the Dataset.
278          *
279          * @param[in] aNetworkKey  A Network Key.
280          *
281          */
SetNetworkKey(const NetworkKey & aNetworkKey)282         void SetNetworkKey(const NetworkKey &aNetworkKey)
283         {
284             mNetworkKey                      = aNetworkKey;
285             mComponents.mIsNetworkKeyPresent = true;
286         }
287 
288         /**
289          * Returns a reference to the Network Key in the Dataset to be updated by caller.
290          *
291          * @returns A reference to the Network Key in the Dataset.
292          *
293          */
UpdateNetworkKey(void)294         NetworkKey &UpdateNetworkKey(void)
295         {
296             mComponents.mIsNetworkKeyPresent = true;
297             return AsCoreType(&mNetworkKey);
298         }
299 
300         /**
301          * Indicates whether or not the Network Name is present in the Dataset.
302          *
303          * @returns TRUE if Network Name is present, FALSE otherwise.
304          *
305          */
IsNetworkNamePresent(void) const306         bool IsNetworkNamePresent(void) const { return mComponents.mIsNetworkNamePresent; }
307 
308         /**
309          * Gets the Network Name in the Dataset.
310          *
311          * MUST be used when Network Name component is present in the Dataset, otherwise its behavior is
312          * undefined.
313          *
314          * @returns The Network Name in the Dataset.
315          *
316          */
GetNetworkName(void) const317         const NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); }
318 
319         /**
320          * Sets the Network Name in the Dataset.
321          *
322          * @param[in] aNetworkNameData   A Network Name Data.
323          *
324          */
SetNetworkName(const NameData & aNetworkNameData)325         void SetNetworkName(const NameData &aNetworkNameData)
326         {
327             IgnoreError(AsCoreType(&mNetworkName).Set(aNetworkNameData));
328             mComponents.mIsNetworkNamePresent = true;
329         }
330 
331         /**
332          * Indicates whether or not the Extended PAN ID is present in the Dataset.
333          *
334          * @returns TRUE if Extended PAN ID is present, FALSE otherwise.
335          *
336          */
IsExtendedPanIdPresent(void) const337         bool IsExtendedPanIdPresent(void) const { return mComponents.mIsExtendedPanIdPresent; }
338 
339         /**
340          * Gets the Extended PAN ID in the Dataset.
341          *
342          * MUST be used when Extended PAN ID component is present in the Dataset, otherwise its behavior is
343          * undefined.
344          *
345          * @returns The Extended PAN ID in the Dataset.
346          *
347          */
GetExtendedPanId(void) const348         const ExtendedPanId &GetExtendedPanId(void) const { return AsCoreType(&mExtendedPanId); }
349 
350         /**
351          * Sets the Extended PAN ID in the Dataset.
352          *
353          * @param[in] aExtendedPanId   An Extended PAN ID.
354          *
355          */
SetExtendedPanId(const ExtendedPanId & aExtendedPanId)356         void SetExtendedPanId(const ExtendedPanId &aExtendedPanId)
357         {
358             mExtendedPanId                      = aExtendedPanId;
359             mComponents.mIsExtendedPanIdPresent = true;
360         }
361 
362         /**
363          * Indicates whether or not the Mesh Local Prefix is present in the Dataset.
364          *
365          * @returns TRUE if Mesh Local Prefix is present, FALSE otherwise.
366          *
367          */
IsMeshLocalPrefixPresent(void) const368         bool IsMeshLocalPrefixPresent(void) const { return mComponents.mIsMeshLocalPrefixPresent; }
369 
370         /**
371          * Gets the Mesh Local Prefix in the Dataset.
372          *
373          * MUST be used when Mesh Local Prefix component is present in the Dataset, otherwise its behavior
374          * is undefined.
375          *
376          * @returns The Mesh Local Prefix in the Dataset.
377          *
378          */
GetMeshLocalPrefix(void) const379         const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const
380         {
381             return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix);
382         }
383 
384         /**
385          * Sets the Mesh Local Prefix in the Dataset.
386          *
387          * @param[in] aMeshLocalPrefix   A Mesh Local Prefix.
388          *
389          */
SetMeshLocalPrefix(const Ip6::NetworkPrefix & aMeshLocalPrefix)390         void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix)
391         {
392             mMeshLocalPrefix                      = aMeshLocalPrefix;
393             mComponents.mIsMeshLocalPrefixPresent = true;
394         }
395 
396         /**
397          * Indicates whether or not the Delay Timer is present in the Dataset.
398          *
399          * @returns TRUE if Delay Timer is present, FALSE otherwise.
400          *
401          */
IsDelayPresent(void) const402         bool IsDelayPresent(void) const { return mComponents.mIsDelayPresent; }
403 
404         /**
405          * Gets the Delay Timer in the Dataset.
406          *
407          * MUST be used when Delay Timer component is present in the Dataset, otherwise its behavior is
408          * undefined.
409          *
410          * @returns The Delay Timer in the Dataset.
411          *
412          */
GetDelay(void) const413         uint32_t GetDelay(void) const { return mDelay; }
414 
415         /**
416          * Sets the Delay Timer in the Dataset.
417          *
418          * @param[in] aDelay  A Delay value.
419          *
420          */
SetDelay(uint32_t aDelay)421         void SetDelay(uint32_t aDelay)
422         {
423             mDelay                      = aDelay;
424             mComponents.mIsDelayPresent = true;
425         }
426 
427         /**
428          * Indicates whether or not the PAN ID is present in the Dataset.
429          *
430          * @returns TRUE if PAN ID is present, FALSE otherwise.
431          *
432          */
IsPanIdPresent(void) const433         bool IsPanIdPresent(void) const { return mComponents.mIsPanIdPresent; }
434 
435         /**
436          * Gets the PAN ID in the Dataset.
437          *
438          * MUST be used when PAN ID component is present in the Dataset, otherwise its behavior is
439          * undefined.
440          *
441          * @returns The PAN ID in the Dataset.
442          *
443          */
GetPanId(void) const444         Mac::PanId GetPanId(void) const { return mPanId; }
445 
446         /**
447          * Sets the PAN ID in the Dataset.
448          *
449          * @param[in] aPanId  A PAN ID.
450          *
451          */
SetPanId(Mac::PanId aPanId)452         void SetPanId(Mac::PanId aPanId)
453         {
454             mPanId                      = aPanId;
455             mComponents.mIsPanIdPresent = true;
456         }
457 
458         /**
459          * Indicates whether or not the Channel is present in the Dataset.
460          *
461          * @returns TRUE if Channel is present, FALSE otherwise.
462          *
463          */
IsChannelPresent(void) const464         bool IsChannelPresent(void) const { return mComponents.mIsChannelPresent; }
465 
466         /**
467          * Gets the Channel in the Dataset.
468          *
469          * MUST be used when Channel component is present in the Dataset, otherwise its behavior is
470          * undefined.
471          *
472          * @returns The Channel in the Dataset.
473          *
474          */
GetChannel(void) const475         uint16_t GetChannel(void) const { return mChannel; }
476 
477         /**
478          * Sets the Channel in the Dataset.
479          *
480          * @param[in] aChannel  A Channel.
481          *
482          */
SetChannel(uint16_t aChannel)483         void SetChannel(uint16_t aChannel)
484         {
485             mChannel                      = aChannel;
486             mComponents.mIsChannelPresent = true;
487         }
488 
489         /**
490          * Indicates whether or not the PSKc is present in the Dataset.
491          *
492          * @returns TRUE if PSKc is present, FALSE otherwise.
493          *
494          */
IsPskcPresent(void) const495         bool IsPskcPresent(void) const { return mComponents.mIsPskcPresent; }
496 
497         /**
498          * Gets the PSKc in the Dataset.
499          *
500          * MUST be used when PSKc component is present in the Dataset, otherwise its behavior is undefined.
501          *
502          * @returns The PSKc in the Dataset.
503          *
504          */
GetPskc(void) const505         const Pskc &GetPskc(void) const { return AsCoreType(&mPskc); }
506 
507         /**
508          * Set the PSKc in the Dataset.
509          *
510          * @param[in] aPskc  A PSKc value.
511          *
512          */
SetPskc(const Pskc & aPskc)513         void SetPskc(const Pskc &aPskc)
514         {
515             mPskc                      = aPskc;
516             mComponents.mIsPskcPresent = true;
517         }
518 
519         /**
520          * Indicates whether or not the Security Policy is present in the Dataset.
521          *
522          * @returns TRUE if Security Policy is present, FALSE otherwise.
523          *
524          */
IsSecurityPolicyPresent(void) const525         bool IsSecurityPolicyPresent(void) const { return mComponents.mIsSecurityPolicyPresent; }
526 
527         /**
528          * Gets the Security Policy in the Dataset.
529          *
530          * MUST be used when Security Policy component is present in the Dataset, otherwise its behavior is
531          * undefined.
532          *
533          * @returns The Security Policy in the Dataset.
534          *
535          */
GetSecurityPolicy(void) const536         const SecurityPolicy &GetSecurityPolicy(void) const { return AsCoreType(&mSecurityPolicy); }
537 
538         /**
539          * Sets the Security Policy in the Dataset.
540          *
541          * @param[in] aSecurityPolicy  A Security Policy to set in Dataset.
542          *
543          */
SetSecurityPolicy(const SecurityPolicy & aSecurityPolicy)544         void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
545         {
546             mSecurityPolicy                      = aSecurityPolicy;
547             mComponents.mIsSecurityPolicyPresent = true;
548         }
549 
550         /**
551          * Indicates whether or not the Channel Mask is present in the Dataset.
552          *
553          * @returns TRUE if Channel Mask is present, FALSE otherwise.
554          *
555          */
IsChannelMaskPresent(void) const556         bool IsChannelMaskPresent(void) const { return mComponents.mIsChannelMaskPresent; }
557 
558         /**
559          * Gets the Channel Mask in the Dataset.
560          *
561          * MUST be used when Channel Mask component is present in the Dataset, otherwise its behavior is
562          * undefined.
563          *
564          * @returns The Channel Mask in the Dataset.
565          *
566          */
GetChannelMask(void) const567         otChannelMask GetChannelMask(void) const { return mChannelMask; }
568 
569         /**
570          * Sets the Channel Mask in the Dataset.
571          *
572          * @param[in] aChannelMask   A Channel Mask value.
573          *
574          */
SetChannelMask(otChannelMask aChannelMask)575         void SetChannelMask(otChannelMask aChannelMask)
576         {
577             mChannelMask                      = aChannelMask;
578             mComponents.mIsChannelMaskPresent = true;
579         }
580 
581         /**
582          * Populates the Dataset with random fields.
583          *
584          * The Network Key, PSKc, Mesh Local Prefix, PAN ID, and Extended PAN ID are generated randomly (crypto-secure)
585          * with Network Name set to "OpenThread-%04x" with PAN ID appended as hex. The Channel is chosen randomly from
586          * radio's preferred channel mask, Channel Mask is set from radio's supported mask, and Security Policy Flags
587          * from current `KeyManager` value.
588          *
589          * @param[in] aInstance    The OpenThread instance.
590          *
591          * @retval kErrorNone If the Dataset was generated successfully.
592          *
593          */
594         Error GenerateRandom(Instance &aInstance);
595 
596         /**
597          * Checks whether the Dataset is a subset of another one, i.e., all the components in the current
598          * Dataset are also present in the @p aOther and the component values fully match.
599          *
600          * The matching of components in the two Datasets excludes Active/Pending Timestamp and Delay components.
601          *
602          * @param[in] aOther   The other Dataset to check against.
603          *
604          * @retval TRUE   The current dataset is a subset of @p aOther.
605          * @retval FALSE  The current Dataset is not a subset of @p aOther.
606          *
607          */
608         bool IsSubsetOf(const Info &aOther) const;
609     };
610 
611     /**
612      * Initializes the object.
613      *
614      */
615     Dataset(void);
616 
617     /**
618      * Clears the Dataset.
619      *
620      */
621     void Clear(void);
622 
623     /**
624      * Indicates whether or not the dataset appears to be well-formed.
625      *
626      * @returns TRUE if the dataset appears to be well-formed, FALSE otherwise.
627      *
628      */
629     bool IsValid(void) const;
630 
631     /**
632      * Indicates whether or not a given TLV type is present in the Dataset.
633      *
634      * @param[in] aType  The TLV type to check.
635      *
636      * @retval TRUE    TLV with @p aType is present in the Dataset.
637      * @retval FALSE   TLV with @p aType is not present in the Dataset.
638      *
639      */
ContainsTlv(Tlv::Type aType) const640     bool ContainsTlv(Tlv::Type aType) const { return (FindTlv(aType) != nullptr); }
641 
642     /**
643      * Indicates whether or not a given TLV type is present in the Dataset.
644      *
645      * @tparam  aTlvType  The TLV type to check.
646      *
647      * @retval TRUE    TLV of @p aTlvType is present in the Dataset.
648      * @retval FALSE   TLV of @p aTlvType is not present in the Dataset.
649      *
650      */
Contains(void) const651     template <typename TlvType> bool Contains(void) const
652     {
653         return ContainsTlv(static_cast<Tlv::Type>(TlvType::kType));
654     }
655 
656     /**
657      * Searches for a given TLV type in the Dataset.
658      *
659      * @param[in] aType  The TLV type to find.
660      *
661      * @returns A pointer to the TLV or `nullptr` if not found.
662      *
663      */
FindTlv(Tlv::Type aType)664     Tlv *FindTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->FindTlv(aType)); }
665 
666     /**
667      * Searches for a given TLV type in the Dataset.
668      *
669      * @param[in] aType  The TLV type to find.
670      *
671      * @returns A pointer to the TLV or `nullptr` if not found.
672      *
673      */
674     const Tlv *FindTlv(Tlv::Type aType) const;
675 
676     /**
677      * Writes a TLV to the Dataset.
678      *
679      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
680      *
681      * @param[in] aTlv     A reference to the TLV.
682      *
683      * @retval kErrorNone    Successfully updated the TLV.
684      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
685      *
686      */
687     Error WriteTlv(const Tlv &aTlv);
688 
689     /**
690      * Writes a TLV in the Dataset.
691      *
692      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
693      *
694      * @param[in]  aType     The TLV type.
695      * @param[in]  aValue    A pointer to a buffer containing the TLV value.
696      * @param[in]  aLength   The TLV length.
697      *
698      * @retval kErrorNone    Successfully updated the TLV.
699      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
700      *
701      */
702     Error WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
703 
704     /**
705      * Writes a simple TLV in the Dataset.
706      *
707      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
708      *
709      * @tparam  SimpleTlvType   The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
710      *
711      * @param[in] aValue   The TLV value.
712      *
713      * @retval kErrorNone    Successfully updated the TLV.
714      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
715      *
716      */
Write(const typename SimpleTlvType::ValueType & aValue)717     template <typename SimpleTlvType> Error Write(const typename SimpleTlvType::ValueType &aValue)
718     {
719         return WriteTlv(static_cast<Tlv::Type>(SimpleTlvType::kType), &aValue, sizeof(aValue));
720     }
721 
722     /**
723      * Writes a `uint` TLV in the Dataset.
724      *
725      * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
726      *
727      * @tparam  UintTlvType     The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
728      *
729      * @param[in]  aValue   The TLV value.
730      *
731      * @retval kErrorNone    Successfully updated the TLV.
732      * @retval kErrorNoBufs  Could not add the TLV due to insufficient buffer space.
733      *
734      */
Write(typename UintTlvType::UintValueType aValue)735     template <typename UintTlvType> Error Write(typename UintTlvType::UintValueType aValue)
736     {
737         typename UintTlvType::UintValueType value = BigEndian::HostSwap(aValue);
738 
739         return WriteTlv(static_cast<Tlv::Type>(UintTlvType::kType), &value, sizeof(value));
740     }
741 
742     /**
743      * Removes a TLV from the Dataset.
744      *
745      * If the Dataset does not contain the given TLV type, no action is performed.
746      *
747      * @param[in] aType  The TLV type to remove.
748      *
749      */
750     void RemoveTlv(Tlv::Type aType);
751 
752     /**
753      * Returns a pointer to the byte representation of the Dataset.
754      *
755      * @returns A pointer to the byte representation of the Dataset.
756      *
757      */
GetBytes(void)758     uint8_t *GetBytes(void) { return mTlvs; }
759 
760     /**
761      * Returns a pointer to the byte representation of the Dataset.
762      *
763      * @returns A pointer to the byte representation of the Dataset.
764      *
765      */
GetBytes(void) const766     const uint8_t *GetBytes(void) const { return mTlvs; }
767 
768     /**
769      * Converts the TLV representation to structure representation.
770      *
771      * @param[out] aDatasetInfo  A reference to `Info` object to output the Dataset.
772      *
773      */
774     void ConvertTo(Info &aDatasetInfo) const;
775 
776     /**
777      * Converts the TLV representation to structure representation.
778      *
779      * @param[out] aTlvs  A reference to output the Dataset as a sequence of TLVs.
780      *
781      */
782     void ConvertTo(Tlvs &aTlvs) const;
783 
784     /**
785      * Returns the Dataset size in bytes.
786      *
787      * @returns The Dataset size in bytes.
788      *
789      */
GetSize(void) const790     uint16_t GetSize(void) const { return mLength; }
791 
792     /**
793      * Sets the Dataset size in bytes.
794      *
795      * @param[in] aSize  The Dataset size in bytes.
796      *
797      */
SetSize(uint16_t aSize)798     void SetSize(uint16_t aSize) { mLength = aSize; }
799 
800     /**
801      * Returns the local time the dataset was last updated.
802      *
803      * @returns The local time the dataset was last updated.
804      *
805      */
GetUpdateTime(void) const806     TimeMilli GetUpdateTime(void) const { return mUpdateTime; }
807 
808     /**
809      * Gets the Timestamp (Active or Pending).
810      *
811      * @param[in]  aType       The type: active or pending.
812      * @param[out] aTimestamp  A reference to a `Timestamp` to output the value.
813      *
814      * @retval kErrorNone      Timestamp was read successfully. @p aTimestamp is updated.
815      * @retval kErrorNotFound  Could not find the requested Timestamp TLV.
816      *
817      */
818     Error GetTimestamp(Type aType, Timestamp &aTimestamp) const;
819 
820     /**
821      * Sets the Timestamp value.
822      *
823      * @param[in] aType        The type: active or pending.
824      * @param[in] aTimestamp   A Timestamp.
825      *
826      */
827     void SetTimestamp(Type aType, const Timestamp &aTimestamp);
828 
829     /**
830      * Reads the Dataset from a given message and checks that it is well-formed and valid.
831      *
832      * @param[in]  aMessage  The message to read from.
833      * @param[in]  aOffset   The offset in @p aMessage to start reading the Dataset TLVs.
834      * @param[in]  aLength   The dataset length in bytes.
835      *
836      * @retval kErrorNone    Successfully read and validated the Dataset.
837      * @retval kErrorParse   Could not read or parse the dataset from @p aMessage.
838      *
839      */
840     Error ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
841 
842     /**
843      * Sets the Dataset using an existing Dataset.
844      *
845      * If this Dataset is an Active Dataset, any Pending Timestamp and Delay Timer TLVs will be omitted in the copy
846      * from @p aDataset.
847      *
848      * @param[in]  aType     The type of the dataset, active or pending.
849      * @param[in]  aDataset  The input Dataset.
850      *
851      */
852     void Set(Type aType, const Dataset &aDataset);
853 
854     /**
855      * Sets the Dataset from a given structure representation.
856      *
857      * @param[in]  aDatasetInfo  The input Dataset as `Dataset::Info`.
858      *
859      * @retval kErrorNone         Successfully set the Dataset.
860      * @retval kErrorInvalidArgs  Dataset is missing Active and/or Pending Timestamp.
861      *
862      */
863     Error SetFrom(const Info &aDatasetInfo);
864 
865     /**
866      * Sets the Dataset using @p aDataset.
867      *
868      * @param[in]  aDataset  The input Dataset as `Tlvs`.
869      *
870      */
871     void SetFrom(const Tlvs &aTlvs);
872 
873     /**
874      * Appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV.
875      *
876      * @param[in] aType          The type of the dataset, active or pending.
877      * @param[in] aMessage       A message to append to.
878      *
879      * @retval kErrorNone    Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
880      * @retval kErrorNoBufs  Insufficient available buffers to append the message with MLE Dataset TLV.
881      *
882      */
883     Error AppendMleDatasetTlv(Type aType, Message &aMessage) const;
884 
885     /**
886      * Applies the Active or Pending Dataset to the Thread interface.
887      *
888      * @param[in]  aInstance            A reference to the OpenThread instance.
889      * @param[out] aIsNetworkKeyUpdated A pointer to where to place whether network key was updated.
890      *
891      * @retval kErrorNone   Successfully applied configuration.
892      * @retval kErrorParse  The dataset has at least one TLV with invalid format.
893      *
894      */
895     Error ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdated = nullptr) const;
896 
897     /**
898      * Converts a Pending Dataset to an Active Dataset.
899      *
900      * Removes the Delay Timer and Pending Timestamp TLVs
901      *
902      */
903     void ConvertToActive(void);
904 
905     /**
906      * Returns a pointer to the start of Dataset TLVs sequence.
907      *
908      * @return  A pointer to the start of Dataset TLVs sequence.
909      *
910      */
GetTlvsStart(void)911     Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); }
912 
913     /**
914      * Returns a pointer to the start of Dataset TLVs sequence.
915      *
916      * @return  A pointer to start of Dataset TLVs sequence.
917      *
918      */
GetTlvsStart(void) const919     const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); }
920 
921     /**
922      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
923      *
924      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
925      *
926      * @return  A pointer to past-the-end of Dataset TLVs sequence.
927      *
928      */
GetTlvsEnd(void)929     Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); }
930 
931     /**
932      * Returns a pointer to the past-the-end of Dataset TLVs sequence.
933      *
934      * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
935      *
936      * @return  A pointer to past-the-end of Dataset TLVs sequence.
937      *
938      */
GetTlvsEnd(void) const939     const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); }
940 
941     /**
942      * Converts a Dataset Type to a string.
943      *
944      * @param[in]  aType   A Dataset type.
945      *
946      */
947     static const char *TypeToString(Type aType);
948 
949 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
950 
951     /**
952      * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero.
953      *
954      * If the Dataset does not contain the @p aTlvType, no action is performed.
955      *
956      * @param[in] aTlvType    The TLV type.
957      * @param[in] aKeyRef     The `KeyRef` to use with secure storage.
958      *
959      */
960     void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
961 
962     /**
963      * Reads and updates a given TLV value in Dataset from secure storage.
964      *
965      * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned.
966      *
967      * @param[in] aTlvType    The TLV type.
968      * @param[in] aKeyRef     The `KeyRef` to use with secure storage.
969      *
970      * @retval kErrorNone    Successfully read the TLV value from secure storage and updated the Dataset.
971      * @retval KErrorFailed  Could not read the @aKeyRef from secure storage.
972      *
973      */
974     Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
975 
976 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
977 
978 private:
979     void RemoveTlv(Tlv *aTlv);
980 
981     uint8_t   mTlvs[kMaxSize]; ///< The Dataset buffer
982     TimeMilli mUpdateTime;     ///< Local time last updated
983     uint16_t  mLength;         ///< The number of valid bytes in @var mTlvs
984 };
985 
986 } // namespace MeshCoP
987 
988 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
989 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
990 
991 } // namespace ot
992 
993 #endif // MESHCOP_DATASET_HPP_
994