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