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 DatasetManager;
62
63 public:
64 static constexpr uint8_t kMaxLength = OT_OPERATIONAL_DATASET_MAX_LENGTH; ///< Max length of Dataset (bytes)
65
66 /**
67 * Represents the Dataset type (active or pending).
68 *
69 */
70 enum Type : uint8_t
71 {
72 kActive, ///< Active Dataset
73 kPending, ///< Pending Dataset
74 };
75
76 /**
77 * Represents a Dataset as a sequence of TLVs.
78 *
79 */
80 typedef otOperationalDatasetTlvs Tlvs;
81
82 /**
83 * Represents a component in Dataset.
84 *
85 */
86 enum Component : uint8_t
87 {
88 kActiveTimestamp, ///< Active Timestamp
89 kPendingTimestamp, ///< Pending Timestamp
90 kNetworkKey, ///< Network Key
91 kNetworkName, ///< Network Name
92 kExtendedPanId, ///< Extended PAN Identifier
93 kMeshLocalPrefix, ///< Mesh Local Prefix
94 kDelay, ///< Delay
95 kPanId, ///< PAN Identifier
96 kChannel, ///< Channel
97 kPskc, ///< PSKc
98 kSecurityPolicy, ///< Security Policy
99 kChannelMask, ///< Channel Mask
100 };
101
102 template <Component kComponent> struct TypeFor; ///< Specifies the associate type for a given `Component`.
103
104 class Info;
105
106 /**
107 * Represents presence of different components in Active or Pending Operational Dataset.
108 *
109 */
110 class Components : public otOperationalDatasetComponents, public Clearable<Components>
111 {
112 friend class Info;
113
114 public:
115 /**
116 * Indicates whether or not the specified `kComponent` is present in the Dataset.
117 *
118 * @tparam kComponent The component to check.
119 *
120 * @retval TRUE The component is present in the Dataset.
121 * @retval FALSE The component is not present in the Dataset.
122 *
123 */
124 template <Component kComponent> bool IsPresent(void) const;
125
126 private:
127 template <Component kComponent> void MarkAsPresent(void);
128 };
129
130 /**
131 * Represents the information about the fields contained an Active or Pending Operational Dataset.
132 *
133 */
134 class Info : public otOperationalDataset, public Clearable<Info>
135 {
136 public:
137 /**
138 * Indicates whether or not the specified component is present in the Dataset.
139 *
140 * @tparam kComponent The component to check.
141 *
142 * @retval TRUE The component is present in the Dataset.
143 * @retval FALSE The component is not present in the Dataset.
144 *
145 */
IsPresent(void) const146 template <Component kComponent> bool IsPresent(void) const { return GetComponents().IsPresent<kComponent>(); }
147
148 /**
149 * Gets the specified component in the Dataset.
150 *
151 * @tparam kComponent The component to check.
152 *
153 * MUST be used when component is present in the Dataset, otherwise its behavior is undefined.
154 *
155 * @returns The component value.
156 *
157 */
158 template <Component kComponent> const typename TypeFor<kComponent>::Type &Get(void) const;
159
160 /**
161 * Gets the specified component in the Dataset.
162 *
163 * @tparam kComponent The component to check.
164 *
165 * MUST be used when component is present in the Dataset, otherwise its behavior is undefined.
166 *
167 * @pram[out] aComponent A reference to output the component value.
168 *
169 */
170 template <Component kComponent> void Get(typename TypeFor<kComponent>::Type &aComponent) const;
171
172 /**
173 * Sets the specified component in the Dataset.
174 *
175 * @tparam kComponent The component to set.
176 *
177 * @param[in] aComponent The component value.
178 *
179 */
Set(const typename TypeFor<kComponent>::Type & aComponent)180 template <Component kComponent> void Set(const typename TypeFor<kComponent>::Type &aComponent)
181 {
182 GetComponents().MarkAsPresent<kComponent>();
183 AsNonConst(Get<kComponent>()) = aComponent;
184 }
185
186 /**
187 * Returns a reference to the specified component in the Dataset to be updated by caller.
188 *
189 * @tparam kComponent The component to set.
190 *
191 * @returns A reference to the component in the Dataset.
192 *
193 */
Update(void)194 template <Component kComponent> typename TypeFor<kComponent>::Type &Update(void)
195 {
196 GetComponents().MarkAsPresent<kComponent>();
197 return AsNonConst(Get<kComponent>());
198 }
199
200 /**
201 * Populates the Dataset with random fields.
202 *
203 * The Network Key, PSKc, Mesh Local Prefix, PAN ID, and Extended PAN ID are generated randomly (crypto-secure)
204 * with Network Name set to "OpenThread-%04x" with PAN ID appended as hex. The Channel is chosen randomly from
205 * radio's preferred channel mask, Channel Mask is set from radio's supported mask, and Security Policy Flags
206 * from current `KeyManager` value.
207 *
208 * @param[in] aInstance The OpenThread instance.
209 *
210 * @retval kErrorNone If the Dataset was generated successfully.
211 *
212 */
213 Error GenerateRandom(Instance &aInstance);
214
215 private:
GetComponents(void)216 Components &GetComponents(void) { return static_cast<Components &>(mComponents); }
GetComponents(void) const217 const Components &GetComponents(void) const { return static_cast<const Components &>(mComponents); }
218 };
219
220 /**
221 * Initializes the object.
222 *
223 */
224 Dataset(void);
225
226 /**
227 * Clears the Dataset.
228 *
229 */
Clear(void)230 void Clear(void) { mLength = 0; }
231
232 /**
233 * Parses and validates all TLVs contained within the Dataset.
234 *
235 * Performs the following checks all TLVs in the Dataset:
236 * - Ensures correct TLV format and expected minimum length for known TLV types that may appear in a Dataset.
237 * - Validates TLV value when applicable (e.g., Channel TLV using a supported channel).
238 * - Ensures no duplicate occurrence of same TLV type.
239 *
240 * @retval kErrorNone Successfully validated all the TLVs in the Dataset.
241 * @retval kErrorParse Dataset TLVs is not well-formed.
242 *
243 */
244 Error ValidateTlvs(void) const;
245
246 /**
247 * Validates the format and value of a given MeshCoP TLV used in Dataset.
248 *
249 * TLV types that can appear in an Active or Pending Operational Dataset are validated. Other TLV types including
250 * unknown TLV types are considered as valid.
251 *
252 * @param[in] aTlv The TLV to validate.
253 *
254 * @retval TRUE The TLV format and value is valid, or TLV type is unknown (not supported in Dataset).
255 * @retval FALSE The TLV format or value is invalid.
256 *
257 */
258 static bool IsTlvValid(const Tlv &aTlv);
259
260 /**
261 * Indicates whether or not a given TLV type is present in the Dataset.
262 *
263 * @param[in] aType The TLV type to check.
264 *
265 * @retval TRUE TLV with @p aType is present in the Dataset.
266 * @retval FALSE TLV with @p aType is not present in the Dataset.
267 *
268 */
ContainsTlv(Tlv::Type aType) const269 bool ContainsTlv(Tlv::Type aType) const { return (FindTlv(aType) != nullptr); }
270
271 /**
272 * Indicates whether or not a given TLV type is present in the Dataset.
273 *
274 * @tparam aTlvType The TLV type to check.
275 *
276 * @retval TRUE TLV of @p aTlvType is present in the Dataset.
277 * @retval FALSE TLV of @p aTlvType is not present in the Dataset.
278 *
279 */
Contains(void) const280 template <typename TlvType> bool Contains(void) const
281 {
282 return ContainsTlv(static_cast<Tlv::Type>(TlvType::kType));
283 }
284
285 /**
286 * Indicates whether or not the Dataset contains all the TLVs from a given array.
287 *
288 * @param[in] aTlvTypes An array of TLV types.
289 * @param[in] aLength Length of @p aTlvTypes array.
290 *
291 * @retval TRUE The Dataset contains all the TLVs in @p aTlvTypes array.
292 * @retval FALSE The Dataset does not contain all the TLVs in @p aTlvTypes array.
293 *
294 */
295 bool ContainsAllTlvs(const Tlv::Type aTlvTypes[], uint8_t aLength) const;
296
297 /**
298 * Indicates whether or not the Dataset contains all the required TLVs for an Active or Pending Dataset.
299 *
300 * @param[in] aType The Dataset type, Active or Pending.
301 *
302 * @retval TRUE The Dataset contains all the required TLVs for @p aType.
303 * @retval FALSE The Dataset does not contain all the required TLVs for @p aType.
304 *
305 */
306 bool ContainsAllRequiredTlvsFor(Type aType) const;
307
308 /**
309 * Searches for a given TLV type in the Dataset.
310 *
311 * @param[in] aType The TLV type to find.
312 *
313 * @returns A pointer to the TLV or `nullptr` if not found.
314 *
315 */
FindTlv(Tlv::Type aType)316 Tlv *FindTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->FindTlv(aType)); }
317
318 /**
319 * Searches for a given TLV type in the Dataset.
320 *
321 * @param[in] aType The TLV type to find.
322 *
323 * @returns A pointer to the TLV or `nullptr` if not found.
324 *
325 */
326 const Tlv *FindTlv(Tlv::Type aType) const;
327
328 /**
329 * Finds and reads a simple TLV in the Dataset.
330 *
331 * If the specified TLV type is not found, `kErrorNotFound` is reported.
332 *
333 * @tparam SimpleTlvType The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
334 *
335 * @param[out] aValue A reference to return the read TLV value.
336 *
337 * @retval kErrorNone Successfully found and read the TLV value. @p aValue is updated.
338 * @retval kErrorNotFound Could not find the TLV in the Dataset.
339 *
340 */
Read(typename SimpleTlvType::ValueType & aValue) const341 template <typename SimpleTlvType> Error Read(typename SimpleTlvType::ValueType &aValue) const
342 {
343 const Tlv *tlv = FindTlv(static_cast<Tlv::Type>(SimpleTlvType::kType));
344
345 return (tlv == nullptr) ? kErrorNotFound : (aValue = tlv->ReadValueAs<SimpleTlvType>(), kErrorNone);
346 }
347
348 /**
349 * Finds and reads an `uint` TLV in the Dataset.
350 *
351 * If the specified TLV type is not found, `kErrorNotFound` is reported.
352 *
353 * @tparam UintTlvType The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
354 *
355 * @param[out] aValue A reference to return the read TLV value.
356 *
357 * @retval kErrorNone Successfully found and read the TLV value. @p aValue is updated.
358 * @retval kErrorNotFound Could not find the TLV in the Dataset.
359 *
360 */
Read(typename UintTlvType::UintValueType & aValue) const361 template <typename UintTlvType> Error Read(typename UintTlvType::UintValueType &aValue) const
362 {
363 const Tlv *tlv = FindTlv(static_cast<Tlv::Type>(UintTlvType::kType));
364
365 return (tlv == nullptr) ? kErrorNotFound : (aValue = tlv->ReadValueAs<UintTlvType>(), kErrorNone);
366 }
367
368 /**
369 * Writes a TLV to the Dataset.
370 *
371 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
372 *
373 * @param[in] aTlv A reference to the TLV.
374 *
375 * @retval kErrorNone Successfully updated the TLV.
376 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
377 *
378 */
379 Error WriteTlv(const Tlv &aTlv);
380
381 /**
382 * Writes a TLV in the Dataset.
383 *
384 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
385 *
386 * @param[in] aType The TLV type.
387 * @param[in] aValue A pointer to a buffer containing the TLV value.
388 * @param[in] aLength The TLV length.
389 *
390 * @retval kErrorNone Successfully updated the TLV.
391 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
392 *
393 */
394 Error WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
395
396 /**
397 * Writes a simple TLV in the Dataset.
398 *
399 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
400 *
401 * @tparam SimpleTlvType The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
402 *
403 * @param[in] aValue The TLV value.
404 *
405 * @retval kErrorNone Successfully updated the TLV.
406 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
407 *
408 */
Write(const typename SimpleTlvType::ValueType & aValue)409 template <typename SimpleTlvType> Error Write(const typename SimpleTlvType::ValueType &aValue)
410 {
411 return WriteTlv(static_cast<Tlv::Type>(SimpleTlvType::kType), &aValue, sizeof(aValue));
412 }
413
414 /**
415 * Writes a `uint` TLV in the Dataset.
416 *
417 * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
418 *
419 * @tparam UintTlvType The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
420 *
421 * @param[in] aValue The TLV value.
422 *
423 * @retval kErrorNone Successfully updated the TLV.
424 * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
425 *
426 */
Write(typename UintTlvType::UintValueType aValue)427 template <typename UintTlvType> Error Write(typename UintTlvType::UintValueType aValue)
428 {
429 typename UintTlvType::UintValueType value = BigEndian::HostSwap(aValue);
430
431 return WriteTlv(static_cast<Tlv::Type>(UintTlvType::kType), &value, sizeof(value));
432 }
433
434 /**
435 * Writes TLVs parsed from a given Dataset into this Dataset.
436 *
437 * TLVs from @p aDataset are parsed and written in the current Dataset. If the same TLV already exists, it will be
438 * replaced. Otherwise, the TLV will be appended.
439 *
440 * @param[in] aDataset A Dataset.
441 *
442 * @retval kErrorNone Successfully merged TLVs from @p Dataset into this Dataset.
443 * @retval kErrorParse The @p aDataset is not valid.
444 * @retval kErrorNoBufs Could not add the TLVs due to insufficient buffer space.
445 *
446 */
447 Error WriteTlvsFrom(const Dataset &aDataset);
448
449 /**
450 * Writes TLVs parsed from a given buffer containing a sequence of TLVs into this Dataset.
451 *
452 * TLVs from @p aTlvs buffer are parsed and written in the current Dataset. If the same TLV already exists, it will
453 * be replaced. Otherwise, the TLV will be appended.
454 *
455 * @param[in] aTlvs A pointer to a buffer containing TLVs.
456 * @param[in] aLength Number of bytes in @p aTlvs buffer.
457 *
458 * @retval kErrorNone Successfully merged TLVs from @p Dataset into this Dataset.
459 * @retval kErrorParse The @p aTlvs is not valid.
460 * @retval kErrorNoBufs Could not add the TLVs due to insufficient buffer space.
461 *
462 */
463 Error WriteTlvsFrom(const uint8_t *aTlvs, uint8_t aLength);
464
465 /**
466 * Writes TLVs corresponding to the components in a given `Dataset::Info` into this Dataset.
467 *
468 * If the same TLV already exists, it will be replaced. Otherwise the TLV will be appended.
469 *
470 * @param[in] aDataseInfo A `Dataset::Info`.
471 *
472 * @retval kErrorNone Successfully merged TLVs from @p aDataseInfo into this Dataset.
473 * @retval kErrorNoBufs Could not add the TLVs due to insufficient buffer space.
474 *
475 */
476 Error WriteTlvsFrom(const Dataset::Info &aDatasetInfo);
477
478 /**
479 * Appends a given sequence of TLVs to the Dataset.
480 *
481 * @note Unlike `WriteTlvsFrom()`, this method does not validate the @p aTlvs to be well-formed or check that there
482 * are no duplicates. It is up to caller to validate the resulting `Dataset` (e.g., using `ValidateTlvs()`) if
483 * desired.
484 *
485 * @param[in] aTlvs A pointer to a buffer containing TLVs.
486 * @param[in] aLength Number of bytes in @p aTlvs buffer.
487 *
488 * @retval kErrorNone Successfully merged TLVs from @p Dataset into this Dataset.
489 * @retval kErrorNoBufs Could not append the TLVs due to insufficient buffer space.
490 *
491 */
492 Error AppendTlvsFrom(const uint8_t *aTlvs, uint8_t aLength);
493
494 /**
495 * Removes a TLV from the Dataset.
496 *
497 * If the Dataset does not contain the given TLV type, no action is performed.
498 *
499 * @param[in] aType The TLV type to remove.
500 *
501 */
502 void RemoveTlv(Tlv::Type aType);
503
504 /**
505 * Reads the Timestamp TLV (Active or Pending).
506 *
507 * @param[in] aType The timestamp type, active or pending.
508 * @param[out] aTimestamp A reference to a `Timestamp` to output the value.
509 *
510 * @retval kErrorNone Timestamp was read successfully. @p aTimestamp is updated.
511 * @retval kErrorNotFound Could not find the requested Timestamp TLV.
512 *
513 */
514 Error ReadTimestamp(Type aType, Timestamp &aTimestamp) const;
515
516 /**
517 * Writes the Timestamp TLV (Active or Pending).
518 *
519 * If the TLV already exists, it will be replaced. Otherwise, the TLV will be appended.
520 *
521 * @param[in] aType The timestamp type, active or pending.
522 * @param[in] aTimestamp The timestamp value.
523 *
524 * @retval kErrorNone Successfully updated the Timestamp TLV.
525 * @retval kErrorNoBufs Could not append the Timestamp TLV due to insufficient buffer space.
526 *
527 */
528 Error WriteTimestamp(Type aType, const Timestamp &aTimestamp);
529
530 /**
531 * Removes the Timestamp TLV (Active or Pending) from the Dataset.
532 *
533 * @param[in] aType The timestamp type, active or pending.
534 *
535 */
536 void RemoveTimestamp(Type aType);
537
538 /**
539 * Returns a pointer to the byte representation of the Dataset.
540 *
541 * @returns A pointer to the byte representation of the Dataset.
542 *
543 */
GetBytes(void)544 uint8_t *GetBytes(void) { return mTlvs; }
545
546 /**
547 * Returns a pointer to the byte representation of the Dataset.
548 *
549 * @returns A pointer to the byte representation of the Dataset.
550 *
551 */
GetBytes(void) const552 const uint8_t *GetBytes(void) const { return mTlvs; }
553
554 /**
555 * Converts the TLV representation to structure representation.
556 *
557 * @param[out] aDatasetInfo A reference to `Info` object to output the Dataset.
558 *
559 */
560 void ConvertTo(Info &aDatasetInfo) const;
561
562 /**
563 * Converts the TLV representation to structure representation.
564 *
565 * @param[out] aTlvs A reference to output the Dataset as a sequence of TLVs.
566 *
567 */
568 void ConvertTo(Tlvs &aTlvs) const;
569
570 /**
571 * Returns the Dataset length in bytes.
572 *
573 * @returns The Dataset length in bytes.
574 *
575 */
GetLength(void) const576 uint8_t GetLength(void) const { return mLength; }
577
578 /**
579 * Sets the Dataset size in bytes.
580 *
581 * @param[in] aSize The Dataset size in bytes.
582 *
583 */
SetLength(uint8_t aLength)584 void SetLength(uint8_t aLength) { mLength = aLength; }
585
586 /**
587 * Returns the local time the dataset was last updated.
588 *
589 * @returns The local time the dataset was last updated.
590 *
591 */
GetUpdateTime(void) const592 TimeMilli GetUpdateTime(void) const { return mUpdateTime; }
593
594 /**
595 * Sets this Dataset using an existing Dataset.
596 *
597 * @param[in] aDataset The input Dataset.
598 *
599 */
600 void SetFrom(const Dataset &aDataset);
601
602 /**
603 * Sets the Dataset from a given structure representation.
604 *
605 * @param[in] aDatasetInfo The input Dataset as `Dataset::Info`.
606 *
607 */
608 void SetFrom(const Info &aDatasetInfo);
609
610 /**
611 * Sets the Dataset from a given sequence of TLVs.
612 *
613 * @param[in] aTlvs The input Dataset as `Tlvs`.
614 *
615 * @retval kErrorNone Successfully set the Dataset.
616 * @retval kErrorInvalidArgs The @p aTlvs is invalid and its length is longer than `kMaxLength`.
617 *
618 */
619 Error SetFrom(const Tlvs &aTlvs);
620
621 /**
622 * Sets the Dataset from a buffer containing a sequence of TLVs.
623 *
624 * @param[in] aTlvs A pointer to a buffer containing TLVs.
625 * @param[in] aLength Number of bytes in @p aTlvs buffer.
626 *
627 * @retval kErrorNone Successfully set the Dataset.
628 * @retval kErrorInvalidArgs @p aLength is longer than `kMaxLength`.
629 *
630 */
631 Error SetFrom(const uint8_t *aTlvs, uint8_t aLength);
632
633 /**
634 * Sets the Dataset by reading the TLVs bytes from given message.
635 *
636 * @param[in] aMessage The message to read from.
637 * @param[in] aOffset The offset in @p aMessage to start reading the Dataset TLVs.
638 * @param[in] aLength The dataset length in bytes.
639 *
640 * @retval kErrorNone Successfully set the Dataset.
641 * @retval kInvalidArgs The @p aLength is longer than `kMaxLength`.
642 * @retval kErrorParse Could not read or parse the dataset from @p aMessage.
643 *
644 */
645 Error SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
646
647 /**
648 * Returns a pointer to the start of Dataset TLVs sequence.
649 *
650 * @return A pointer to the start of Dataset TLVs sequence.
651 *
652 */
GetTlvsStart(void)653 Tlv *GetTlvsStart(void) { return reinterpret_cast<Tlv *>(mTlvs); }
654
655 /**
656 * Returns a pointer to the start of Dataset TLVs sequence.
657 *
658 * @return A pointer to start of Dataset TLVs sequence.
659 *
660 */
GetTlvsStart(void) const661 const Tlv *GetTlvsStart(void) const { return reinterpret_cast<const Tlv *>(mTlvs); }
662
663 /**
664 * Returns a pointer to the past-the-end of Dataset TLVs sequence.
665 *
666 * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
667 *
668 * @return A pointer to past-the-end of Dataset TLVs sequence.
669 *
670 */
GetTlvsEnd(void)671 Tlv *GetTlvsEnd(void) { return reinterpret_cast<Tlv *>(mTlvs + mLength); }
672
673 /**
674 * Returns a pointer to the past-the-end of Dataset TLVs sequence.
675 *
676 * Note that past-the-end points to the byte after the end of the last TLV in Dataset TLVs sequence.
677 *
678 * @return A pointer to past-the-end of Dataset TLVs sequence.
679 *
680 */
GetTlvsEnd(void) const681 const Tlv *GetTlvsEnd(void) const { return reinterpret_cast<const Tlv *>(mTlvs + mLength); }
682
683 /**
684 * Determines whether this Dataset is a subset of another Dataset.
685 *
686 * The Dataset is considered a subset if all of its TLVs, excluding Active/Pending Timestamp and Delay Timer TLVs,
687 * are present in the @p aOther Dataset and the TLV values match exactly.
688 *
689 * @param[in] aOther The other Dataset to check against.
690 *
691 * @retval TRUE The current Dataset is a subset of @p aOther.
692 * @retval FALSE The current Dataset is not a subset of @p aOther.
693 *
694 */
695 bool IsSubsetOf(const Dataset &aOther) const;
696
697 /**
698 * Converts a Dataset Type to a string.
699 *
700 * @param[in] aType A Dataset type.
701 *
702 */
703 static const char *TypeToString(Type aType);
704
705 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
706
707 /**
708 * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero.
709 *
710 * If the Dataset does not contain the @p aTlvType, no action is performed.
711 *
712 * @param[in] aTlvType The TLV type.
713 * @param[in] aKeyRef The `KeyRef` to use with secure storage.
714 *
715 */
716 void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
717
718 /**
719 * Reads and updates a given TLV value in Dataset from secure storage.
720 *
721 * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned.
722 *
723 * @param[in] aTlvType The TLV type.
724 * @param[in] aKeyRef The `KeyRef` to use with secure storage.
725 *
726 * @retval kErrorNone Successfully read the TLV value from secure storage and updated the Dataset.
727 * @retval KErrorFailed Could not read the @aKeyRef from secure storage.
728 *
729 */
730 Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
731
732 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
733
734 private:
735 void RemoveTlv(Tlv *aTlv);
736
TimestampTlvFor(Type aType)737 static Tlv::Type TimestampTlvFor(Type aType)
738 {
739 return (aType == kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp;
740 }
741
742 uint8_t mTlvs[kMaxLength];
743 uint8_t mLength;
744 TimeMilli mUpdateTime; // Local time last updated
745 };
746
747 //---------------------------------------------------------------------------------------------------------------------
748 // Template specializations
749
750 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
751 // `Dataset::Components::IsPresent()` and `Dataset::Components::MarkAsPresent()`
752
753 #define DefineIsPresentAndMarkAsPresent(Component) \
754 template <> inline bool Dataset::Components::IsPresent<Dataset::k##Component>(void) const \
755 { \
756 return mIs##Component##Present; \
757 } \
758 \
759 template <> inline void Dataset::Components::MarkAsPresent<Dataset::k##Component>(void) \
760 { \
761 mIs##Component##Present = true; \
762 }
763
764 // clang-format off
765
766 DefineIsPresentAndMarkAsPresent(ActiveTimestamp)
767 DefineIsPresentAndMarkAsPresent(PendingTimestamp)
768 DefineIsPresentAndMarkAsPresent(NetworkKey)
769 DefineIsPresentAndMarkAsPresent(NetworkName)
770 DefineIsPresentAndMarkAsPresent(ExtendedPanId)
771 DefineIsPresentAndMarkAsPresent(MeshLocalPrefix)
772 DefineIsPresentAndMarkAsPresent(Delay)
773 DefineIsPresentAndMarkAsPresent(PanId)
774 DefineIsPresentAndMarkAsPresent(Channel)
775 DefineIsPresentAndMarkAsPresent(Pskc)
776 DefineIsPresentAndMarkAsPresent(SecurityPolicy)
777 DefineIsPresentAndMarkAsPresent(ChannelMask)
778
779 #undef DefineIsPresentAndMarkAsPresent
780
781 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
782 // `Dataset::TypeFor<>`
783
784 template <> struct Dataset::TypeFor<Dataset::kActiveTimestamp> { using Type = Timestamp; };
785 template <> struct Dataset::TypeFor<Dataset::kPendingTimestamp> { using Type = Timestamp; };
786 template <> struct Dataset::TypeFor<Dataset::kNetworkKey> { using Type = NetworkKey; };
787 template <> struct Dataset::TypeFor<Dataset::kNetworkName> { using Type = NetworkName; };
788 template <> struct Dataset::TypeFor<Dataset::kExtendedPanId> { using Type = ExtendedPanId; };
789 template <> struct Dataset::TypeFor<Dataset::kMeshLocalPrefix> { using Type = Ip6::NetworkPrefix; };
790 template <> struct Dataset::TypeFor<Dataset::kDelay> { using Type = uint32_t; };
791 template <> struct Dataset::TypeFor<Dataset::kPanId> { using Type = Mac::PanId; };
792 template <> struct Dataset::TypeFor<Dataset::kChannel> { using Type = uint16_t; };
793 template <> struct Dataset::TypeFor<Dataset::kPskc> { using Type = Pskc; };
794 template <> struct Dataset::TypeFor<Dataset::kSecurityPolicy> { using Type = SecurityPolicy; };
795 template <> struct Dataset::TypeFor<Dataset::kChannelMask> { using Type = uint32_t; };
796
797 // clang-format on
798
799 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
800 // Dataset::Info::Get<>()
801
Get(void) const802 template <> inline const NetworkKey &Dataset::Info::Get<Dataset::kNetworkKey>(void) const
803 {
804 return AsCoreType(&mNetworkKey);
805 }
806
Get(void) const807 template <> inline const NetworkName &Dataset::Info::Get<Dataset::kNetworkName>(void) const
808 {
809 return AsCoreType(&mNetworkName);
810 }
811
Get(void) const812 template <> inline const ExtendedPanId &Dataset::Info::Get<Dataset::kExtendedPanId>(void) const
813 {
814 return AsCoreType(&mExtendedPanId);
815 }
816
Get(void) const817 template <> inline const Ip6::NetworkPrefix &Dataset::Info::Get<Dataset::kMeshLocalPrefix>(void) const
818 {
819 return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix);
820 }
821
Get(void) const822 template <> inline const uint32_t &Dataset::Info::Get<Dataset::kDelay>(void) const { return mDelay; }
823
Get(void) const824 template <> inline const Mac::PanId &Dataset::Info::Get<Dataset::kPanId>(void) const { return mPanId; }
825
Get(void) const826 template <> inline const uint16_t &Dataset::Info::Get<Dataset::kChannel>(void) const { return mChannel; }
827
Get(void) const828 template <> inline const Pskc &Dataset::Info::Get<Dataset::kPskc>(void) const { return AsCoreType(&mPskc); }
829
Get(void) const830 template <> inline const SecurityPolicy &Dataset::Info::Get<Dataset::kSecurityPolicy>(void) const
831 {
832 return AsCoreType(&mSecurityPolicy);
833 }
834
Get(void) const835 template <> inline const uint32_t &Dataset::Info::Get<Dataset::kChannelMask>(void) const { return mChannelMask; }
836
837 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
838 // Active and Pending Timestamp
839
Get(Timestamp & aTimestamp) const840 template <> inline void Dataset::Info::Get<Dataset::kActiveTimestamp>(Timestamp &aTimestamp) const
841 {
842 aTimestamp.SetFrom(mActiveTimestamp);
843 }
844
Get(Timestamp & aTimestamp) const845 template <> inline void Dataset::Info::Get<Dataset::kPendingTimestamp>(Timestamp &aTimestamp) const
846 {
847 aTimestamp.SetFrom(mPendingTimestamp);
848 }
849
Set(const Timestamp & aTimestamp)850 template <> inline void Dataset::Info::Set<Dataset::kActiveTimestamp>(const Timestamp &aTimestamp)
851 {
852 GetComponents().MarkAsPresent<kActiveTimestamp>();
853 aTimestamp.ConvertTo(mActiveTimestamp);
854 }
855
Set(const Timestamp & aTimestamp)856 template <> inline void Dataset::Info::Set<Dataset::kPendingTimestamp>(const Timestamp &aTimestamp)
857 {
858 GetComponents().MarkAsPresent<kPendingTimestamp>();
859 aTimestamp.ConvertTo(mPendingTimestamp);
860 }
861
862 } // namespace MeshCoP
863
864 DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
865 DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
866
867 } // namespace ot
868
869 #endif // MESHCOP_DATASET_HPP_
870