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