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