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