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 generating and processing Thread Network Data TLVs.
32 */
33
34 #ifndef NETWORK_DATA_TLVS_HPP_
35 #define NETWORK_DATA_TLVS_HPP_
36
37 #include "openthread-core-config.h"
38
39 #include <openthread/netdata.h>
40
41 #include "common/const_cast.hpp"
42 #include "common/debug.hpp"
43 #include "common/encoding.hpp"
44 #include "common/equatable.hpp"
45 #include "net/ip6_address.hpp"
46 #include "thread/mle_types.hpp"
47 #include "thread/network_data_types.hpp"
48
49 namespace ot {
50 namespace NetworkData {
51
52 /**
53 * @addtogroup core-netdata-tlvs
54 *
55 * @brief
56 * This module includes definitions for generating and processing Thread Network Data TLVs.
57 *
58 * @{
59 *
60 */
61
62 class NetworkDataTlv;
63
64 /**
65 * Casts a `NetworkDataTlv` pointer to a given subclass `TlvType` pointer.
66 *
67 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
68 *
69 * @param[in] aTlv A pointer to a `NetworkDataTlv` to convert/cast to a `TlvType`.
70 *
71 * @returns A `TlvType` pointer to `aTlv`.
72 *
73 */
As(NetworkDataTlv * aTlv)74 template <class TlvType> TlvType *As(NetworkDataTlv *aTlv) { return static_cast<TlvType *>(aTlv); }
75
76 /**
77 * Casts a `NetworkDataTlv` pointer to a given subclass `TlvType` pointer.
78 *
79 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
80 *
81 * @param[in] aTlv A pointer to a `NetworkDataTlv` to convert/cast to a `TlvType`.
82 *
83 * @returns A `TlvType` pointer to `aTlv`.
84 *
85 */
As(const NetworkDataTlv * aTlv)86 template <class TlvType> const TlvType *As(const NetworkDataTlv *aTlv) { return static_cast<const TlvType *>(aTlv); }
87
88 /**
89 * Casts a `NetworkDataTlv` reference to a given subclass `TlvType` reference.
90 *
91 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
92 *
93 * @param[in] aTlv A reference to a `NetworkDataTlv` to convert/cast to a `TlvType`.
94 *
95 * @returns A `TlvType` reference to `aTlv`.
96 *
97 */
As(NetworkDataTlv & aTlv)98 template <class TlvType> TlvType &As(NetworkDataTlv &aTlv) { return static_cast<TlvType &>(aTlv); }
99
100 /**
101 * Casts a `NetworkDataTlv` reference to a given subclass `TlvType` reference.
102 *
103 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
104 *
105 * @param[in] aTlv A reference to a `NetworkDataTlv` to convert/cast to a `TlvType`.
106 *
107 * @returns A `TlvType` reference to `aTlv`.
108 *
109 */
As(const NetworkDataTlv & aTlv)110 template <class TlvType> const TlvType &As(const NetworkDataTlv &aTlv) { return static_cast<const TlvType &>(aTlv); }
111
112 /**
113 * Implements Thread Network Data TLV generation and parsing.
114 *
115 */
116 OT_TOOL_PACKED_BEGIN
117 class NetworkDataTlv
118 {
119 public:
120 /**
121 * Thread Network Data Type values.
122 *
123 */
124 enum Type : uint8_t
125 {
126 kTypeHasRoute = 0, ///< Has Route TLV
127 kTypePrefix = 1, ///< Prefix TLV
128 kTypeBorderRouter = 2, ///< Border Router TLV
129 kTypeContext = 3, ///< Context TLV
130 kTypeCommissioningData = 4, ///< Commissioning Dataset TLV
131 kTypeService = 5, ///< Service TLV
132 kTypeServer = 6, ///< Server TLV
133 };
134
135 /**
136 * Initializes the TLV.
137 *
138 */
Init(void)139 void Init(void)
140 {
141 mType = 0;
142 mLength = 0;
143 }
144
145 /**
146 * Returns the Type value.
147 *
148 * @returns The Type value.
149 *
150 */
GetType(void) const151 Type GetType(void) const { return static_cast<Type>(mType >> kTypeOffset); }
152
153 /**
154 * Sets the Type value.
155 *
156 * @param[in] aType The Type value.
157 *
158 */
SetType(Type aType)159 void SetType(Type aType) { mType = (mType & ~kTypeMask) | ((aType << kTypeOffset) & kTypeMask); }
160
161 /**
162 * Returns the Length value.
163 *
164 * @returns The Length value.
165 *
166 */
GetLength(void) const167 uint8_t GetLength(void) const { return mLength; }
168
169 /**
170 * Sets the Length value.
171 *
172 * @param[in] aLength The Length value.
173 *
174 */
SetLength(uint8_t aLength)175 void SetLength(uint8_t aLength) { mLength = aLength; }
176
177 /**
178 * Increases the Length value by a given amount.
179 *
180 * @param[in] aIncrement The increment amount to increase the length.
181 *
182 */
IncreaseLength(uint8_t aIncrement)183 void IncreaseLength(uint8_t aIncrement) { mLength += aIncrement; }
184
185 /**
186 * Decreases the Length value by a given amount.
187 *
188 * @param[in] aDecrement The decrement amount to decrease the length.
189 *
190 */
DecreaseLength(uint8_t aDecrement)191 void DecreaseLength(uint8_t aDecrement) { mLength -= aDecrement; }
192
193 /**
194 * Returns the TLV's total size (number of bytes) including Type, Length, and Value fields.
195 *
196 * @returns The total size include Type, Length, and Value fields.
197 *
198 */
GetSize(void) const199 uint8_t GetSize(void) const { return sizeof(NetworkDataTlv) + mLength; }
200
201 /**
202 * Returns a pointer to the Value.
203 *
204 * @returns A pointer to the value.
205 *
206 */
GetValue(void)207 uint8_t *GetValue(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(NetworkDataTlv); }
208
209 /**
210 * Returns a pointer to the Value.
211 *
212 * @returns A pointer to the value.
213 *
214 */
GetValue(void) const215 const uint8_t *GetValue(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(NetworkDataTlv); }
216
217 /**
218 * Returns a pointer to the next Network Data TLV.
219 *
220 * @returns A pointer to the next Network Data TLV.
221 *
222 */
GetNext(void)223 NetworkDataTlv *GetNext(void)
224 {
225 return reinterpret_cast<NetworkDataTlv *>(reinterpret_cast<uint8_t *>(this) + sizeof(*this) + mLength);
226 }
227
228 /**
229 * Returns a pointer to the next Network Data TLV.
230 *
231 * @returns A pointer to the next Network Data TLV.
232 *
233 */
GetNext(void) const234 const NetworkDataTlv *GetNext(void) const
235 {
236 return reinterpret_cast<const NetworkDataTlv *>(reinterpret_cast<const uint8_t *>(this) + sizeof(*this) +
237 mLength);
238 }
239
240 /**
241 * Clears the Stable bit.
242 *
243 */
ClearStable(void)244 void ClearStable(void) { mType &= ~kStableMask; }
245
246 /**
247 * Indicates whether or not the Stable bit is set.
248 *
249 * @retval TRUE If the Stable bit is set.
250 * @retval FALSE If the Stable bit is not set.
251 *
252 */
IsStable(void) const253 bool IsStable(void) const { return (mType & kStableMask); }
254
255 /**
256 * Sets the Stable bit.
257 *
258 */
SetStable(void)259 void SetStable(void) { mType |= kStableMask; }
260
261 /**
262 * Searches in a given sequence of TLVs to find the first TLV with a given type.
263 *
264 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
265 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
266 * @param[in] aType The TLV type to find.
267 *
268 * @returns A pointer to the TLV if found, or `nullptr` if not found.
269 *
270 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,Type aType)271 static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType)
272 {
273 return AsNonConst(Find(AsConst(aStart), AsConst(aEnd), aType));
274 }
275
276 /**
277 * Searches in a given sequence of TLVs to find the first TLV with a given type.
278 *
279 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
280 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
281 * @param[in] aType The TLV type to find.
282 *
283 * @returns A pointer to the TLV if found, or `nullptr` if not found.
284 *
285 */
286 static const NetworkDataTlv *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, Type aType);
287
288 /**
289 * This template static method searches in a given sequence of TLVs to find the first TLV with a given type.
290 *
291 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
292 *
293 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
294 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
295 *
296 * @returns A pointer to the TLV if found, or `nullptr` if not found.
297 *
298 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd)299 template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd)
300 {
301 return As<TlvType>(Find(aStart, aEnd, TlvType::kType));
302 }
303
304 /**
305 * This template static method searches in a given sequence of TLVs to find the first TLV with a given type.
306 *
307 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
308 *
309 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
310 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
311 *
312 * @returns A pointer to the TLV if found, or `nullptr` if not found.
313 *
314 */
Find(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)315 template <typename TlvType> static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
316 {
317 return As<TlvType>(Find(aStart, aEnd, TlvType::kType));
318 }
319
320 /**
321 * Searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable
322 * flag.
323 *
324 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
325 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
326 * @param[in] aType The TLV type to find.
327 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
328 *
329 * @returns A pointer to the TLV if found, or `nullptr` if not found.
330 *
331 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,Type aType,bool aStable)332 static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType, bool aStable)
333 {
334 return AsNonConst(Find(AsConst(aStart), AsConst(aEnd), aType, aStable));
335 }
336
337 /**
338 * Searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable
339 * flag.
340 *
341 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
342 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
343 * @param[in] aType The TLV type to find.
344 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
345 *
346 * @returns A pointer to the TLV if found, or `nullptr` if not found.
347 *
348 */
349 static const NetworkDataTlv *Find(const NetworkDataTlv *aStart,
350 const NetworkDataTlv *aEnd,
351 Type aType,
352 bool aStable);
353
354 /**
355 * This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and
356 * stable flag.
357 *
358 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
359 *
360 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
361 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
362 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
363 *
364 * @returns A pointer to the TLV if found, or `nullptr` if not found.
365 *
366 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,bool aStable)367 template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable)
368 {
369 return As<TlvType>(Find(aStart, aEnd, TlvType::kType, aStable));
370 }
371
372 /**
373 * This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and
374 * stable flag.
375 *
376 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
377 *
378 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
379 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
380 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
381 *
382 * @returns A pointer to the TLV if found, or `nullptr` if not found.
383 *
384 */
385 template <typename TlvType>
Find(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd,bool aStable)386 static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, bool aStable)
387 {
388 return As<TlvType>(Find(aStart, aEnd, TlvType::kType, aStable));
389 }
390
391 private:
392 static constexpr uint8_t kTypeOffset = 1;
393 static constexpr uint8_t kTypeMask = 0x7f << kTypeOffset;
394 static constexpr uint8_t kStableMask = 1 << 0;
395
396 uint8_t mType;
397 uint8_t mLength;
398 } OT_TOOL_PACKED_END;
399
400 /**
401 * Implements Has Route TLV entry generation and parsing.
402 *
403 */
404 OT_TOOL_PACKED_BEGIN
405 class HasRouteEntry : public Equatable<HasRouteEntry>
406 {
407 friend class ExternalRouteConfig;
408
409 public:
410 /**
411 * Initializes the header.
412 *
413 */
Init(void)414 void Init(void)
415 {
416 SetRloc(Mle::kInvalidRloc16);
417 mFlags = 0;
418 }
419
420 /**
421 * Returns the RLOC16 value.
422 *
423 * @returns The RLOC16 value.
424 */
GetRloc(void) const425 uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
426
427 /**
428 * Sets the RLOC16 value.
429 *
430 * @param[in] aRloc16 The RLOC16 value.
431 *
432 */
SetRloc(uint16_t aRloc16)433 void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
434
435 /**
436 * Returns the Preference value.
437 *
438 * @returns The preference value.
439 *
440 */
GetPreference(void) const441 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
442
443 /**
444 * Gets the Flags value.
445 *
446 * @returns The Flags value.
447 *
448 */
GetFlags(void) const449 uint8_t GetFlags(void) const { return mFlags; }
450
451 /**
452 * Sets the Flags value.
453 *
454 * @param[in] aFlags The Flags value.
455 *
456 */
SetFlags(uint8_t aFlags)457 void SetFlags(uint8_t aFlags) { mFlags = aFlags; }
458
459 /**
460 * Indicates whether or not the NAT64 flag is set.
461 *
462 * @retval TRUE If the NAT64 flag is set.
463 * @retval FALSE If the NAT64 flag is not set.
464 *
465 */
IsNat64(void) const466 bool IsNat64(void) const { return (mFlags & kNat64Flag) != 0; }
467
468 /**
469 * Indicates whether or not the Advertising PIO (AP) flag is set.
470 *
471 * @retval TRUE If the AP flag is set.
472 * @retval FALSE If the AP flag is not set.
473 *
474 */
IsAdvPio(void) const475 bool IsAdvPio(void) const { return (mFlags & kAdvPioFlag) != 0; }
476
477 /**
478 * Returns a pointer to the next HasRouteEntry.
479 *
480 * @returns A pointer to the next HasRouteEntry.
481 *
482 */
GetNext(void)483 HasRouteEntry *GetNext(void) { return (this + 1); }
484
485 /**
486 * Returns a pointer to the next HasRouteEntry.
487 *
488 * @returns A pointer to the next HasRouteEntry.
489 *
490 */
GetNext(void) const491 const HasRouteEntry *GetNext(void) const { return (this + 1); }
492
493 /**
494 * Returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
495 * given flags bitmask.
496 *
497 * @param[in] aFlags The flags bitmask.
498 *
499 * @returns An updated version @p aFlags with preference bits cleared.
500 *
501 */
FlagsWithoutPreference(uint8_t aFlags)502 static uint8_t FlagsWithoutPreference(uint8_t aFlags) { return (aFlags & ~kPreferenceMask); }
503
504 /**
505 * Gets the preference field from a flags bitmask.
506 *
507 * @param[in] aFlags The flags.
508 *
509 * @returns The preference field from the @p aFlags.
510 *
511 */
PreferenceFromFlags(uint8_t aFlags)512 static int8_t PreferenceFromFlags(uint8_t aFlags) { return RoutePreferenceFromValue(aFlags >> kPreferenceOffset); }
513
514 private:
515 static constexpr uint8_t kPreferenceOffset = 6;
516 static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
517 static constexpr uint8_t kNat64Flag = 1 << 5;
518 static constexpr uint8_t kAdvPioFlag = 1 << 4;
519
520 uint16_t mRloc;
521 uint8_t mFlags;
522 } OT_TOOL_PACKED_END;
523
524 /**
525 * Implements Has Route TLV generation and parsing.
526 *
527 */
528 OT_TOOL_PACKED_BEGIN
529 class HasRouteTlv : public NetworkDataTlv
530 {
531 public:
532 static constexpr Type kType = kTypeHasRoute; ///< The TLV Type.
533
534 /**
535 * Initializes the TLV.
536 *
537 */
Init(void)538 void Init(void)
539 {
540 NetworkDataTlv::Init();
541 SetType(kTypeHasRoute);
542 SetLength(0);
543 }
544
545 /**
546 * Returns the number of HasRoute entries.
547 *
548 * @returns The number of HasRoute entries.
549 *
550 */
GetNumEntries(void) const551 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(HasRouteEntry); }
552
553 /**
554 * Returns a pointer to the HasRoute entry at a given index.
555 *
556 * @param[in] aIndex An index.
557 *
558 * @returns A pointer to the HasRoute entry at @p aIndex.
559 *
560 */
GetEntry(uint8_t aIndex)561 HasRouteEntry *GetEntry(uint8_t aIndex)
562 {
563 return reinterpret_cast<HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry)));
564 }
565
566 /**
567 * Returns a pointer to the HasRoute entry at a given index.
568 *
569 * @param[in] aIndex An index.
570 *
571 * @returns A pointer to the HasRoute entry at @p aIndex.
572 *
573 */
GetEntry(uint8_t aIndex) const574 const HasRouteEntry *GetEntry(uint8_t aIndex) const
575 {
576 return reinterpret_cast<const HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry)));
577 }
578
579 /**
580 * Returns a pointer to the first HasRouteEntry (at index 0'th).
581 *
582 * @returns A pointer to the first HasRouteEntry.
583 *
584 */
GetFirstEntry(void)585 HasRouteEntry *GetFirstEntry(void) { return reinterpret_cast<HasRouteEntry *>(GetValue()); }
586
587 /**
588 * Returns a pointer to the first HasRouteEntry (at index 0'th).
589 *
590 * @returns A pointer to the first HasRouteEntry.
591 *
592 */
GetFirstEntry(void) const593 const HasRouteEntry *GetFirstEntry(void) const { return reinterpret_cast<const HasRouteEntry *>(GetValue()); }
594
595 /**
596 * Returns a pointer to the last HasRouteEntry.
597 *
598 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
599 *
600 * @returns A pointer to the last HasRouteEntry.
601 *
602 */
GetLastEntry(void)603 HasRouteEntry *GetLastEntry(void)
604 {
605 return reinterpret_cast<HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry));
606 }
607
608 /**
609 * Returns a pointer to the last HasRouteEntry.
610 *
611 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
612 *
613 * @returns A pointer to the last HasRouteEntry.
614 *
615 */
GetLastEntry(void) const616 const HasRouteEntry *GetLastEntry(void) const
617 {
618 return reinterpret_cast<const HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry));
619 }
620
621 } OT_TOOL_PACKED_END;
622
623 /**
624 * Implements Prefix TLV generation and parsing.
625 *
626 */
627 OT_TOOL_PACKED_BEGIN
628 class PrefixTlv : public NetworkDataTlv
629 {
630 public:
631 static constexpr Type kType = kTypePrefix; ///< The TLV Type.
632
633 /**
634 * Initializes the TLV.
635 *
636 * @param[in] aDomainId The Domain ID.
637 * @param[in] aPrefixLength The Prefix Length in bits.
638 * @param[in] aPrefix A pointer to the prefix.
639 *
640 */
Init(uint8_t aDomainId,uint8_t aPrefixLength,const uint8_t * aPrefix)641 void Init(uint8_t aDomainId, uint8_t aPrefixLength, const uint8_t *aPrefix)
642 {
643 NetworkDataTlv::Init();
644 SetType(kTypePrefix);
645 mDomainId = aDomainId;
646 mPrefixLength = aPrefixLength;
647 memcpy(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength));
648 SetSubTlvsLength(0);
649 }
650
651 /**
652 * Initializes the TLV.
653 *
654 * @param[in] aDomainId The Domain ID.
655 * @param[in] aPrefix The Prefix.
656 *
657 */
Init(uint8_t aDomainId,const Ip6::Prefix aPrefix)658 void Init(uint8_t aDomainId, const Ip6::Prefix aPrefix)
659 {
660 Init(aDomainId, aPrefix.GetLength(), aPrefix.GetBytes());
661 }
662
663 /**
664 * Indicates whether or not the TLV appears to be well-formed.
665 *
666 * @retval TRUE If the TLV appears to be well-formed.
667 * @retval FALSE If the TLV does not appear to be well-formed.
668 *
669 */
IsValid(void) const670 bool IsValid(void) const
671 {
672 return ((GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv)) &&
673 (GetLength() >= Ip6::Prefix::SizeForLength(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv)) &&
674 (Ip6::Prefix::SizeForLength(mPrefixLength) <= sizeof(Ip6::Address)));
675 }
676
677 /**
678 * Returns the Domain ID value.
679 *
680 * @returns The Domain ID value.
681 *
682 */
GetDomainId(void) const683 uint8_t GetDomainId(void) const { return mDomainId; }
684
685 /**
686 * Returns the Prefix Length value.
687 *
688 * @returns The Prefix Length value (in bits).
689 *
690 */
GetPrefixLength(void) const691 uint8_t GetPrefixLength(void) const { return mPrefixLength; }
692
693 /**
694 * Returns a pointer to the Prefix.
695 *
696 * @returns A pointer to the Prefix.
697 *
698 */
GetPrefix(void)699 uint8_t *GetPrefix(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
700
701 /**
702 * Returns a pointer to the Prefix.
703 *
704 * @returns A pointer to the Prefix.
705 *
706 */
GetPrefix(void) const707 const uint8_t *GetPrefix(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
708
709 /**
710 * Copies the Prefix from TLV into a given `Ip6::Prefix`.
711 *
712 * @param[out] aPrefix An `Ip6::Prefix` to copy the Prefix from TLV into.
713 *
714 */
CopyPrefixTo(Ip6::Prefix & aPrefix) const715 void CopyPrefixTo(Ip6::Prefix &aPrefix) const { aPrefix.Set(GetPrefix(), GetPrefixLength()); }
716
717 /**
718 * Indicates whether the Prefix from TLV is equal to a given `Ip6::Prefix`.
719 *
720 * @param[in] aPrefix A Prefix to compare with.
721 *
722 * @retval TRUE The TLV's Prefix is equal to @p aPrefix.
723 * @retval FALSE The TLV's Prefix is not equal to @p aPrefix.
724 *
725 */
IsEqual(Ip6::Prefix & aPrefix) const726 bool IsEqual(Ip6::Prefix &aPrefix) const { return aPrefix.IsEqual(GetPrefix(), GetPrefixLength()); }
727
728 /**
729 * Indicates whether the Prefix from TLV is equal to a given Prefix.
730 *
731 * @param[in] aPrefix A pointer to an IPv6 prefix to compare with.
732 * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits).
733 *
734 * @retval TRUE The TLV's Prefix is equal to @p aPrefix.
735 * @retval FALSE The TLV's Prefix is not equal @p aPrefix.
736 *
737 */
IsEqual(const uint8_t * aPrefix,uint8_t aPrefixLength) const738 bool IsEqual(const uint8_t *aPrefix, uint8_t aPrefixLength) const
739 {
740 return (aPrefixLength == mPrefixLength) &&
741 (Ip6::Prefix::MatchLength(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)) >=
742 mPrefixLength);
743 }
744
745 /**
746 * Returns a pointer to the Sub-TLVs.
747 *
748 * @returns A pointer to the Sub-TLVs.
749 *
750 */
GetSubTlvs(void)751 NetworkDataTlv *GetSubTlvs(void)
752 {
753 return reinterpret_cast<NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength));
754 }
755
756 /**
757 * Returns a pointer to the Sub-TLVs.
758 *
759 * @returns A pointer to the Sub-TLVs.
760 *
761 */
GetSubTlvs(void) const762 const NetworkDataTlv *GetSubTlvs(void) const
763 {
764 return reinterpret_cast<const NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength));
765 }
766
767 /**
768 * Returns the Sub-TLVs length in bytes.
769 *
770 * @returns The Sub-TLVs length in bytes.
771 *
772 */
GetSubTlvsLength(void) const773 uint8_t GetSubTlvsLength(void) const
774 {
775 return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength));
776 }
777
778 /**
779 * Sets the Sub-TLVs length in bytes.
780 *
781 * @param[in] aLength The Sub-TLVs length in bytes.
782 *
783 */
SetSubTlvsLength(uint8_t aLength)784 void SetSubTlvsLength(uint8_t aLength)
785 {
786 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength) + aLength);
787 }
788
789 /**
790 * Searches in the sub-TLVs to find the first one matching a given TLV type.
791 *
792 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
793 *
794 * @returns A pointer to the TLV if found, or `nullptr` if not found.
795 *
796 */
FindSubTlv(void)797 template <typename SubTlvType> SubTlvType *FindSubTlv(void)
798 {
799 return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
800 }
801
802 /**
803 * Searches in the sub-TLVs to find the first one matching a given TLV Type.
804 *
805 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
806 *
807 * @returns A pointer to the TLV if found, or `nullptr` if not found.
808 *
809 */
FindSubTlv(void) const810 template <typename SubTlvType> const SubTlvType *FindSubTlv(void) const
811 {
812 return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
813 }
814
815 /**
816 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
817 *
818 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
819 *
820 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
821 *
822 * @returns A pointer to the TLV if found, or `nullptr` if not found.
823 *
824 */
FindSubTlv(bool aStable)825 template <typename SubTlvType> SubTlvType *FindSubTlv(bool aStable)
826 {
827 return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
828 }
829
830 /**
831 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
832 *
833 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
834 *
835 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
836 *
837 * @returns A pointer to the TLV if found, or `nullptr` if not found.
838 *
839 */
FindSubTlv(bool aStable) const840 template <typename SubTlvType> const SubTlvType *FindSubTlv(bool aStable) const
841 {
842 return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
843 }
844
845 /**
846 * Searches in the sub-TLVs to find the first one matching a given TLV type.
847 *
848 * @param[in] aType The sub-TLV type to search for.
849 *
850 * @returns A pointer to the TLV if found, or `nullptr` if not found.
851 *
852 */
FindSubTlv(Type aType)853 NetworkDataTlv *FindSubTlv(Type aType) { return AsNonConst(AsConst(this)->FindSubTlv(aType)); }
854
855 /**
856 * Searches in the sub-TLVs to find the first one matching a given TLV type.
857 *
858 * @param[in] aType The sub-TLV type to search for.
859 *
860 * @returns A pointer to the TLV if found, or `nullptr` if not found.
861 *
862 */
863 const NetworkDataTlv *FindSubTlv(Type aType) const;
864
865 /**
866 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
867 *
868 * @param[in] aType The sub-TLV type to search for.
869 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
870 *
871 * @returns A pointer to the TLV if found, or `nullptr` if not found.
872 *
873 */
FindSubTlv(Type aType,bool aStable)874 NetworkDataTlv *FindSubTlv(Type aType, bool aStable)
875 {
876 return AsNonConst(AsConst(this)->FindSubTlv(aType, aStable));
877 }
878
879 /**
880 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
881 *
882 * @param[in] aType The sub-TLV type to search for.
883 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
884 *
885 * @returns A pointer to the TLV if found, or `nullptr` if not found.
886 *
887 */
888 const NetworkDataTlv *FindSubTlv(Type aType, bool aStable) const;
889
890 /**
891 * Calculates the total size (number of bytes) of a Prefix TLV with a given Prefix Length value.
892 *
893 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any
894 * sub TLVs of the Prefix TLV.
895 *
896 * @param[in] aPrefixLength A Prefix Length in bits.
897
898 * @returns The size (number of bytes) of the Prefix TLV.
899 *
900 */
CalculateSize(uint8_t aPrefixLength)901 static uint16_t CalculateSize(uint8_t aPrefixLength)
902 {
903 return sizeof(PrefixTlv) + Ip6::Prefix::SizeForLength(aPrefixLength);
904 }
905
906 private:
907 uint8_t mDomainId;
908 uint8_t mPrefixLength;
909 } OT_TOOL_PACKED_END;
910
911 /**
912 * Implements Border Router Entry generation and parsing.
913 *
914 */
915 OT_TOOL_PACKED_BEGIN
916 class BorderRouterEntry : public Equatable<BorderRouterEntry>
917 {
918 friend class OnMeshPrefixConfig;
919
920 public:
921 /**
922 * Initializes the TLV.
923 *
924 */
Init(void)925 void Init(void)
926 {
927 SetRloc(Mle::kInvalidRloc16);
928 mFlags = 0;
929 }
930
931 /**
932 * Returns the RLOC16 value.
933 *
934 * @returns The RLOC16 value.
935 */
GetRloc(void) const936 uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
937
938 /**
939 * Sets the RLOC16 value.
940 *
941 * @param[in] aRloc16 The RLOC16 value.
942 *
943 */
SetRloc(uint16_t aRloc16)944 void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
945
946 /**
947 * Returns the Flags value.
948 *
949 * @returns The Flags value.
950 *
951 */
GetFlags(void) const952 uint16_t GetFlags(void) const { return BigEndian::HostSwap16(mFlags); }
953
954 /**
955 * Sets the Flags value.
956 *
957 * @param[in] aFlags The Flags value.
958 *
959 */
SetFlags(uint16_t aFlags)960 void SetFlags(uint16_t aFlags) { mFlags = BigEndian::HostSwap16(aFlags); }
961
962 /**
963 * Returns the Preference value.
964 *
965 * @returns the Preference value.
966 *
967 */
GetPreference(void) const968 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
969
970 /**
971 * Indicates whether or not the Preferred flag is set.
972 *
973 * @retval TRUE If the Preferred flag is set.
974 * @retval FALSE If the Preferred flag is not set.
975 *
976 */
IsPreferred(void) const977 bool IsPreferred(void) const { return (BigEndian::HostSwap16(mFlags) & kPreferredFlag) != 0; }
978
979 /**
980 * Indicates whether or not the SLAAC flag is set.
981 *
982 * @retval TRUE If the SLAAC flag is set.
983 * @retval FALSE If the SLAAC flag is not set.
984 *
985 */
IsSlaac(void) const986 bool IsSlaac(void) const { return (BigEndian::HostSwap16(mFlags) & kSlaacFlag) != 0; }
987
988 /**
989 * Indicates whether or not the DHCP flag is set.
990 *
991 * @retval TRUE If the DHCP flag is set.
992 * @retval FALSE If the DHCP flag is not set.
993 *
994 */
IsDhcp(void) const995 bool IsDhcp(void) const { return (BigEndian::HostSwap16(mFlags) & kDhcpFlag) != 0; }
996
997 /**
998 * Indicates whether or not the Configure flag is set.
999 *
1000 * @retval TRUE If the Configure flag is set.
1001 * @retval FALSE If the Configure flag is not set.
1002 *
1003 */
IsConfigure(void) const1004 bool IsConfigure(void) const { return (BigEndian::HostSwap16(mFlags) & kConfigureFlag) != 0; }
1005
1006 /**
1007 * Indicates whether or not the Default Route flag is set.
1008 *
1009 * @retval TRUE If the Default Route flag is set.
1010 * @retval FALSE If the Default Route flag is not set.
1011 *
1012 */
IsDefaultRoute(void) const1013 bool IsDefaultRoute(void) const { return (BigEndian::HostSwap16(mFlags) & kDefaultRouteFlag) != 0; }
1014
1015 /**
1016 * Indicates whether or not the On-Mesh flag is set.
1017 *
1018 * @retval TRUE If the On-Mesh flag is set.
1019 * @retval FALSE If the On-Mesh flag is not set.
1020 *
1021 */
IsOnMesh(void) const1022 bool IsOnMesh(void) const { return (BigEndian::HostSwap16(mFlags) & kOnMeshFlag) != 0; }
1023
1024 /**
1025 * Indicates whether or not the Nd-Dns flag is set.
1026 *
1027 * @retval TRUE If the Nd-Dns flag is set.
1028 * @retval FALSE If the Nd-Dns flag is not set.
1029 *
1030 */
IsNdDns(void) const1031 bool IsNdDns(void) const { return (BigEndian::HostSwap16(mFlags) & kNdDnsFlag) != 0; }
1032
1033 /**
1034 * Indicates whether or not the Domain Prefix flag is set.
1035 *
1036 * @retval TRUE If the Domain Prefix flag is set.
1037 * @retval FALSE If the Domain Prefix flag is not set.
1038 *
1039 */
IsDp(void) const1040 bool IsDp(void) const { return (BigEndian::HostSwap16(mFlags) & kDpFlag) != 0; }
1041
1042 /**
1043 * Returns a pointer to the next BorderRouterEntry
1044 *
1045 * @returns A pointer to the next BorderRouterEntry.
1046 *
1047 */
GetNext(void)1048 BorderRouterEntry *GetNext(void) { return (this + 1); }
1049
1050 /**
1051 * Returns a pointer to the next BorderRouterEntry
1052 *
1053 * @returns A pointer to the next BorderRouterEntry.
1054 *
1055 */
GetNext(void) const1056 const BorderRouterEntry *GetNext(void) const { return (this + 1); }
1057
1058 /**
1059 * Returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
1060 * given flags bitmask.
1061 *
1062 * @param[in] aFlags The flags bitmask.
1063 *
1064 * @returns An updated version @p aFlags with preference bits cleared.
1065 *
1066 */
FlagsWithoutPreference(uint16_t aFlags)1067 static uint16_t FlagsWithoutPreference(uint16_t aFlags) { return (aFlags & ~kPreferenceMask); }
1068
1069 /**
1070 * Gets the preference field from a flags bitmask.
1071 *
1072 * @param[in] aFlags The flags.
1073 *
1074 * @returns The preference field from the @p aFlags.
1075 *
1076 */
PreferenceFromFlags(uint16_t aFlags)1077 static int8_t PreferenceFromFlags(uint16_t aFlags)
1078 {
1079 return RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> kPreferenceOffset));
1080 }
1081
1082 private:
1083 static constexpr uint8_t kPreferenceOffset = 14;
1084 static constexpr uint16_t kPreferenceMask = 3 << kPreferenceOffset;
1085 static constexpr uint16_t kPreferredFlag = 1 << 13;
1086 static constexpr uint16_t kSlaacFlag = 1 << 12;
1087 static constexpr uint16_t kDhcpFlag = 1 << 11;
1088 static constexpr uint16_t kConfigureFlag = 1 << 10;
1089 static constexpr uint16_t kDefaultRouteFlag = 1 << 9;
1090 static constexpr uint16_t kOnMeshFlag = 1 << 8;
1091 static constexpr uint16_t kNdDnsFlag = 1 << 7;
1092 static constexpr uint16_t kDpFlag = 1 << 6;
1093
1094 uint16_t mRloc;
1095 uint16_t mFlags;
1096 } OT_TOOL_PACKED_END;
1097
1098 /**
1099 * Implements Border Router TLV generation and parsing.
1100 *
1101 */
1102 OT_TOOL_PACKED_BEGIN
1103 class BorderRouterTlv : public NetworkDataTlv
1104 {
1105 public:
1106 static constexpr Type kType = kTypeBorderRouter; ///< The TLV Type.
1107
1108 /**
1109 * Initializes the TLV.
1110 *
1111 */
Init(void)1112 void Init(void)
1113 {
1114 NetworkDataTlv::Init();
1115 SetType(kTypeBorderRouter);
1116 SetLength(0);
1117 }
1118
1119 /**
1120 * Returns the number of Border Router entries.
1121 *
1122 * @returns The number of Border Router entries.
1123 *
1124 */
GetNumEntries(void) const1125 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(BorderRouterEntry); }
1126
1127 /**
1128 * Returns a pointer to the Border Router entry at a given index
1129 *
1130 * @param[in] aIndex The index.
1131 *
1132 * @returns A pointer to the Border Router entry at @p aIndex.
1133 *
1134 */
GetEntry(uint8_t aIndex)1135 BorderRouterEntry *GetEntry(uint8_t aIndex)
1136 {
1137 return reinterpret_cast<BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry)));
1138 }
1139
1140 /**
1141 * Returns a pointer to the Border Router entry at a given index.
1142 *
1143 * @param[in] aIndex The index.
1144 *
1145 * @returns A pointer to the Border Router entry at @p aIndex
1146 *
1147 */
GetEntry(uint8_t aIndex) const1148 const BorderRouterEntry *GetEntry(uint8_t aIndex) const
1149 {
1150 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry)));
1151 }
1152
1153 /**
1154 * Returns a pointer to the first BorderRouterEntry (at index 0'th).
1155 *
1156 * @returns A pointer to the first BorderRouterEntry.
1157 *
1158 */
GetFirstEntry(void)1159 BorderRouterEntry *GetFirstEntry(void) { return reinterpret_cast<BorderRouterEntry *>(GetValue()); }
1160
1161 /**
1162 * Returns a pointer to the first BorderRouterEntry (at index 0'th).
1163 *
1164 * @returns A pointer to the first BorderRouterEntry.
1165 *
1166 */
GetFirstEntry(void) const1167 const BorderRouterEntry *GetFirstEntry(void) const
1168 {
1169 return reinterpret_cast<const BorderRouterEntry *>(GetValue());
1170 }
1171
1172 /**
1173 * Returns a pointer to the last BorderRouterEntry.
1174 *
1175 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
1176 *
1177 * @returns A pointer to the last BorderRouterEntry.
1178 *
1179 */
GetLastEntry(void)1180 BorderRouterEntry *GetLastEntry(void)
1181 {
1182 return reinterpret_cast<BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry));
1183 }
1184
1185 /**
1186 * Returns a pointer to the last BorderRouterEntry.
1187 *
1188 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
1189 *
1190 * @returns A pointer to the last BorderRouterEntry.
1191 *
1192 */
GetLastEntry(void) const1193 const BorderRouterEntry *GetLastEntry(void) const
1194 {
1195 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry));
1196 }
1197
1198 } OT_TOOL_PACKED_END;
1199
1200 /**
1201 * Implements Context TLV generation and processing.
1202 *
1203 */
1204 OT_TOOL_PACKED_BEGIN
1205 class ContextTlv : public NetworkDataTlv
1206 {
1207 public:
1208 static constexpr Type kType = kTypeContext; ///< The TLV Type.
1209
1210 /**
1211 * Initializes the Context TLV.
1212 *
1213 * @param[in] aContextId The Context ID value.
1214 * @param[in] aContextLength The Context Length value.
1215 *
1216 */
Init(uint8_t aContextId,uint8_t aContextLength)1217 void Init(uint8_t aContextId, uint8_t aContextLength)
1218 {
1219 NetworkDataTlv::Init();
1220 SetType(kTypeContext);
1221 SetLength(sizeof(ContextTlv) - sizeof(NetworkDataTlv));
1222 mFlags = ((aContextId << kContextIdOffset) & kContextIdMask);
1223 mContextLength = aContextLength;
1224 }
1225
1226 /**
1227 * Indicates whether or not the Compress flag is set.
1228 *
1229 * @retval TRUE The Compress flag is set.
1230 * @retval FALSE The Compress flags is not set.
1231 *
1232 */
IsCompress(void) const1233 bool IsCompress(void) const { return (mFlags & kCompressFlag) != 0; }
1234
1235 /**
1236 * Clears the Compress flag.
1237 *
1238 */
ClearCompress(void)1239 void ClearCompress(void) { mFlags &= ~kCompressFlag; }
1240
1241 /**
1242 * Sets the Compress flag.
1243 *
1244 */
SetCompress(void)1245 void SetCompress(void) { mFlags |= kCompressFlag; }
1246
1247 /**
1248 * Returns the Context ID value.
1249 *
1250 * @returns The Context ID value.
1251 *
1252 */
GetContextId(void) const1253 uint8_t GetContextId(void) const { return mFlags & kContextIdMask; }
1254
1255 /**
1256 * Returns the Context Length value.
1257 *
1258 * @returns The Context Length value.
1259 *
1260 */
GetContextLength(void) const1261 uint8_t GetContextLength(void) const { return mContextLength; }
1262
1263 private:
1264 static constexpr uint8_t kCompressFlag = 1 << 4;
1265 static constexpr uint8_t kContextIdOffset = 0;
1266 static constexpr uint8_t kContextIdMask = 0xf << kContextIdOffset;
1267
1268 uint8_t mFlags;
1269 uint8_t mContextLength;
1270 } OT_TOOL_PACKED_END;
1271
1272 /**
1273 * Implements Commissioning Data TLV generation and parsing.
1274 *
1275 */
1276 OT_TOOL_PACKED_BEGIN
1277 class CommissioningDataTlv : public NetworkDataTlv
1278 {
1279 public:
1280 static constexpr Type kType = kTypeCommissioningData; ///< The TLV Type.
1281
1282 /**
1283 * Initializes the TLV.
1284 *
1285 */
Init(void)1286 void Init(void)
1287 {
1288 NetworkDataTlv::Init();
1289 SetType(kTypeCommissioningData);
1290 SetLength(0);
1291 }
1292 } OT_TOOL_PACKED_END;
1293
1294 /**
1295 * Implements Service Data TLV generation and parsing.
1296 *
1297 */
1298 OT_TOOL_PACKED_BEGIN
1299 class ServiceTlv : public NetworkDataTlv
1300 {
1301 public:
1302 static constexpr Type kType = kTypeService; ///< The TLV Type.
1303
1304 static constexpr uint32_t kThreadEnterpriseNumber = 44970; ///< Thread enterprise number.
1305
1306 /**
1307 * Initializes the TLV.
1308 *
1309 * @param[in] aServiceId The Service Id value.
1310 * @param[in] aEnterpriseNumber The Enterprise Number.
1311 * @param[in] aServiceData The Service Data.
1312 *
1313 */
1314 void Init(uint8_t aServiceId, uint32_t aEnterpriseNumber, const ServiceData &aServiceData);
1315
1316 /**
1317 * Indicates whether or not the TLV appears to be well-formed.
1318 *
1319 * @retval TRUE If the TLV appears to be well-formed.
1320 * @retval FALSE If the TLV does not appear to be well-formed.
1321 *
1322 */
IsValid(void) const1323 bool IsValid(void) const
1324 {
1325 uint8_t length = GetLength();
1326
1327 return (length >= sizeof(mFlagsServiceId)) &&
1328 (length >= kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t))) &&
1329 (static_cast<uint16_t>(length) + sizeof(NetworkDataTlv) >=
1330 CalculateSize(GetEnterpriseNumber(), GetServiceDataLength()));
1331 }
1332
1333 /**
1334 * Returns the Service ID. It is in range 0x00-0x0f.
1335 *
1336 * @returns the Service ID.
1337 *
1338 */
GetServiceId(void) const1339 uint8_t GetServiceId(void) const { return (mFlagsServiceId & kServiceIdMask); }
1340
1341 /**
1342 * Returns Enterprise Number field.
1343 *
1344 * @returns The Enterprise Number.
1345 *
1346 */
GetEnterpriseNumber(void) const1347 uint32_t GetEnterpriseNumber(void) const
1348 {
1349 return IsThreadEnterprise() ? static_cast<uint32_t>(kThreadEnterpriseNumber)
1350 : BigEndian::HostSwap32(mShared.mEnterpriseNumber);
1351 }
1352
1353 /**
1354 * Gets the Service Data.
1355 *
1356 * @param[out] aServiceData A reference to a`ServiceData` to return the data.
1357 *
1358 */
GetServiceData(ServiceData & aServiceData) const1359 void GetServiceData(ServiceData &aServiceData) const
1360 {
1361 aServiceData.Init(GetServiceData(), GetServiceDataLength());
1362 }
1363
1364 /**
1365 * Gets Service Data length.
1366 *
1367 * @returns length of the Service Data field in bytes.
1368 *
1369 */
GetServiceDataLength(void) const1370 uint8_t GetServiceDataLength(void) const
1371 {
1372 return IsThreadEnterprise() ? mShared.mServiceDataLengthThreadEnterprise : mServiceDataLength;
1373 }
1374
1375 /**
1376 * Returns the Sub-TLVs length in bytes.
1377 *
1378 * @returns The Sub-TLVs length in bytes.
1379 *
1380 */
GetSubTlvsLength(void)1381 uint8_t GetSubTlvsLength(void) { return GetLength() - GetFieldsLength(); }
1382
1383 /**
1384 * Sets the Sub-TLVs length in bytes.
1385 *
1386 * @param[in] aLength The Sub-TLVs length in bytes.
1387 *
1388 */
SetSubTlvsLength(uint8_t aLength)1389 void SetSubTlvsLength(uint8_t aLength) { SetLength(GetFieldsLength() + aLength); }
1390
1391 /**
1392 * Returns a pointer to the Sub-TLVs.
1393 *
1394 * @returns A pointer to the Sub-TLVs.
1395 *
1396 */
GetSubTlvs(void)1397 NetworkDataTlv *GetSubTlvs(void) { return reinterpret_cast<NetworkDataTlv *>(GetValue() + GetFieldsLength()); }
1398
1399 /**
1400 * Returns a pointer to the Sub-TLVs.
1401 *
1402 * @returns A pointer to the Sub-TLVs.
1403 *
1404 */
GetSubTlvs(void) const1405 const NetworkDataTlv *GetSubTlvs(void) const
1406 {
1407 return reinterpret_cast<const NetworkDataTlv *>(GetValue() + GetFieldsLength());
1408 }
1409
1410 /**
1411 * Calculates the total size (number of bytes) of a Service TLV with a given Enterprise Number
1412 * and Service Data length.
1413 *
1414 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any
1415 * sub-TLVs of the Service TLV.
1416 *
1417 * @param[in] aEnterpriseNumber A Enterprise Number.
1418 * @param[in] aServiceDataLength A Service Data length.
1419 *
1420 * @returns The size (number of bytes) of the Service TLV.
1421 *
1422 */
CalculateSize(uint32_t aEnterpriseNumber,uint8_t aServiceDataLength)1423 static uint16_t CalculateSize(uint32_t aEnterpriseNumber, uint8_t aServiceDataLength)
1424 {
1425 return sizeof(NetworkDataTlv) + kMinLength + aServiceDataLength +
1426 ((aEnterpriseNumber == kThreadEnterpriseNumber) ? 0 : sizeof(uint32_t) /* mEnterpriseNumber */);
1427 }
1428
1429 private:
IsThreadEnterprise(void) const1430 bool IsThreadEnterprise(void) const { return (mFlagsServiceId & kThreadEnterpriseFlag) != 0; }
1431
GetServiceData(void) const1432 const uint8_t *GetServiceData(void) const
1433 {
1434 return (IsThreadEnterprise() ? &mShared.mServiceDataLengthThreadEnterprise : &mServiceDataLength) +
1435 sizeof(uint8_t);
1436 }
1437
GetFieldsLength(void) const1438 uint8_t GetFieldsLength(void) const
1439 {
1440 // Returns the length of TLV value's common fields (flags, enterprise
1441 // number and service data) excluding any sub-TLVs.
1442
1443 return kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t)) + GetServiceDataLength();
1444 }
1445
1446 static constexpr uint8_t kThreadEnterpriseFlag = (1 << 7);
1447 static constexpr uint8_t kServiceIdMask = 0xf;
1448 static constexpr uint8_t kMinLength = sizeof(uint8_t) + sizeof(uint8_t); // Flags & Service Data length.
1449
1450 // When `kThreadEnterpriseFlag is set in the `mFlagsServiceId`, the
1451 // `mEnterpriseNumber` field is elided and `mFlagsServiceId` is
1452 // immediately followed by the Service Data length field (which is
1453 // represented by `mServiceDataLengthThreadEnterprise`)
1454
1455 uint8_t mFlagsServiceId;
1456 union OT_TOOL_PACKED_FIELD
1457 {
1458 uint32_t mEnterpriseNumber;
1459 uint8_t mServiceDataLengthThreadEnterprise;
1460 } mShared;
1461 uint8_t mServiceDataLength;
1462
1463 } OT_TOOL_PACKED_END;
1464
1465 /**
1466 * Implements Server Data TLV generation and parsing.
1467 *
1468 */
1469 OT_TOOL_PACKED_BEGIN
1470 class ServerTlv : public NetworkDataTlv
1471 {
1472 public:
1473 static constexpr Type kType = kTypeServer; ///< The TLV Type.
1474
1475 /**
1476 * Initializes the Server TLV.
1477 *
1478 * @param[in] aServer16 The Server16 value.
1479 * @param[in] aServerData The Server Data.
1480 *
1481 */
Init(uint16_t aServer16,const ServerData & aServerData)1482 void Init(uint16_t aServer16, const ServerData &aServerData)
1483 {
1484 NetworkDataTlv::Init();
1485 SetType(kTypeServer);
1486 SetServer16(aServer16);
1487 aServerData.CopyBytesTo(GetServerData());
1488 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + aServerData.GetLength());
1489 }
1490
1491 /**
1492 * Indicates whether or not the TLV appears to be well-formed.
1493 *
1494 * @retval TRUE If the TLV appears to be well-formed.
1495 * @retval FALSE If the TLV does not appear to be well-formed.
1496 *
1497 */
IsValid(void) const1498 bool IsValid(void) const { return GetLength() >= (sizeof(*this) - sizeof(NetworkDataTlv)); }
1499
1500 /**
1501 * Returns the Server16 value.
1502 *
1503 * @returns The Server16 value.
1504 *
1505 */
GetServer16(void) const1506 uint16_t GetServer16(void) const { return BigEndian::HostSwap16(mServer16); }
1507
1508 /*
1509 * Sets the Server16 value.
1510 *
1511 * @param[in] aServer16 The Server16 value.
1512 *
1513 */
SetServer16(uint16_t aServer16)1514 void SetServer16(uint16_t aServer16) { mServer16 = BigEndian::HostSwap16(aServer16); }
1515
1516 /**
1517 * Gets the Server Data.
1518 *
1519 * @param[out] aServerData A reference to a`ServerData` to return the data.
1520 *
1521 */
GetServerData(ServerData & aServerData) const1522 void GetServerData(ServerData &aServerData) const { aServerData.Init(GetServerData(), GetServerDataLength()); }
1523
1524 /**
1525 * Returns the Server Data length in bytes.
1526 *
1527 * @returns The Server Data length in bytes.
1528 *
1529 */
GetServerDataLength(void) const1530 uint8_t GetServerDataLength(void) const { return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv)); }
1531
1532 /**
1533 * Indicates whether two Server TLVs fully match.
1534 *
1535 * @param[in] aOther Another Server TLV to compare with it.
1536 *
1537 * @retval TRUE The two TLVs are equal.
1538 * @retval FALSE The two TLVs are not equal.
1539 *
1540 */
operator ==(const ServerTlv & aOther) const1541 bool operator==(const ServerTlv &aOther) const
1542 {
1543 return (GetLength() == aOther.GetLength()) && (memcmp(GetValue(), aOther.GetValue(), GetLength()) == 0);
1544 }
1545
1546 /**
1547 * Calculates the total size (number of bytes) of a Service TLV with a given Server Data length.
1548 *
1549 * Note that the returned size does include the Type and Length fields in the TLV.
1550 *
1551 * @param[in] aServerDataLength Server Data length in bytes.
1552 *
1553 * @returns The size (number of bytes) of the Server TLV.
1554 *
1555 */
CalculateSize(uint8_t aServerDataLength)1556 static uint16_t CalculateSize(uint8_t aServerDataLength) { return sizeof(ServerTlv) + aServerDataLength; }
1557
1558 private:
GetServerData(void) const1559 const uint8_t *GetServerData(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
GetServerData(void)1560 uint8_t *GetServerData(void) { return AsNonConst(AsConst(this)->GetServerData()); }
1561
1562 uint16_t mServer16;
1563 } OT_TOOL_PACKED_END;
1564
1565 /**
1566 * Represents a Network Data TLV iterator.
1567 *
1568 */
1569 class TlvIterator
1570 {
1571 public:
1572 /**
1573 * Initializes the `TlvIterator` to iterate over a given sequence of TLVs.
1574 *
1575 * @param[in] aStart A pointer to the start of the TLV sequence.
1576 * @param[in] aEnd A pointer to the end of the TLV sequence.
1577 *
1578 */
TlvIterator(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)1579 TlvIterator(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
1580 : mStart(aStart)
1581 , mEnd(aEnd)
1582 {
1583 }
1584
1585 /**
1586 * Initializes the `TlvIterator` to iterate over TLVs from a given buffer.
1587 *
1588 * @param[in] aBuffer A pointer to a buffer containing the TLVs.
1589 * @param[in] aLength The length (number of bytes) of @p aBuffer.
1590 *
1591 */
TlvIterator(const uint8_t * aBuffer,uint8_t aLength)1592 TlvIterator(const uint8_t *aBuffer, uint8_t aLength)
1593 : TlvIterator(reinterpret_cast<const NetworkDataTlv *>(aBuffer),
1594 reinterpret_cast<const NetworkDataTlv *>(aBuffer + aLength))
1595 {
1596 }
1597
1598 /**
1599 * Initializes the `TlvIterator` to iterate over sub-TLVs of a given Prefix TLV.
1600 *
1601 * @param[in] aPrefixTlv A Prefix TLV to iterate over its sub-TLVs.
1602 *
1603 */
TlvIterator(const PrefixTlv & aPrefixTlv)1604 explicit TlvIterator(const PrefixTlv &aPrefixTlv)
1605 : TlvIterator(aPrefixTlv.GetSubTlvs(), aPrefixTlv.GetNext())
1606 {
1607 }
1608
1609 /**
1610 * Initializes the `TlvIterator` to iterate over sub-TLVs of a given Service TLV.
1611 *
1612 * @param[in] aServiceTlv A Service TLV to iterate over its sub-TLVs.
1613 *
1614 */
TlvIterator(const ServiceTlv & aServiceTlv)1615 explicit TlvIterator(const ServiceTlv &aServiceTlv)
1616 : TlvIterator(aServiceTlv.GetSubTlvs(), aServiceTlv.GetNext())
1617 {
1618 }
1619
1620 /**
1621 * Iterates to the next TLV with a given type.
1622 *
1623 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
1624 *
1625 * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
1626 *
1627 */
Iterate(void)1628 template <typename TlvType> const TlvType *Iterate(void) { return As<TlvType>(Iterate(TlvType::kType)); }
1629
1630 /**
1631 * Iterates to the next TLV with a given type and stable flag.
1632 *
1633 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
1634 *
1635 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
1636 *
1637 * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
1638 *
1639 */
Iterate(bool aStable)1640 template <typename TlvType> const TlvType *Iterate(bool aStable)
1641 {
1642 return As<TlvType>(Iterate(TlvType::kType, aStable));
1643 }
1644
1645 private:
1646 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType);
1647 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType, bool aStable);
1648
1649 const NetworkDataTlv *mStart;
1650 const NetworkDataTlv *mEnd;
1651 };
1652
1653 /**
1654 * @}
1655 *
1656 */
1657
1658 } // namespace NetworkData
1659 } // namespace ot
1660
1661 #endif // NETWORK_DATA_TLVS_HPP_
1662