1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file includes definitions for generating and processing Thread Network Data TLVs.
32 */
33
34 #ifndef NETWORK_DATA_TLVS_HPP_
35 #define NETWORK_DATA_TLVS_HPP_
36
37 #include "openthread-core-config.h"
38
39 #include <openthread/netdata.h>
40
41 #include "common/const_cast.hpp"
42 #include "common/debug.hpp"
43 #include "common/encoding.hpp"
44 #include "common/equatable.hpp"
45 #include "net/ip6_address.hpp"
46 #include "thread/mle_types.hpp"
47 #include "thread/network_data_types.hpp"
48
49 namespace ot {
50 namespace NetworkData {
51
52 /**
53 * @addtogroup core-netdata-tlvs
54 *
55 * @brief
56 * This module includes definitions for generating and processing Thread Network Data TLVs.
57 *
58 * @{
59 */
60
61 class NetworkDataTlv;
62
63 /**
64 * Casts a `NetworkDataTlv` pointer to a given subclass `TlvType` pointer.
65 *
66 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
67 *
68 * @param[in] aTlv A pointer to a `NetworkDataTlv` to convert/cast to a `TlvType`.
69 *
70 * @returns A `TlvType` pointer to `aTlv`.
71 */
As(NetworkDataTlv * aTlv)72 template <class TlvType> TlvType *As(NetworkDataTlv *aTlv) { return static_cast<TlvType *>(aTlv); }
73
74 /**
75 * Casts a `NetworkDataTlv` pointer to a given subclass `TlvType` pointer.
76 *
77 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
78 *
79 * @param[in] aTlv A pointer to a `NetworkDataTlv` to convert/cast to a `TlvType`.
80 *
81 * @returns A `TlvType` pointer to `aTlv`.
82 */
As(const NetworkDataTlv * aTlv)83 template <class TlvType> const TlvType *As(const NetworkDataTlv *aTlv) { return static_cast<const TlvType *>(aTlv); }
84
85 /**
86 * Casts a `NetworkDataTlv` reference to a given subclass `TlvType` reference.
87 *
88 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
89 *
90 * @param[in] aTlv A reference to a `NetworkDataTlv` to convert/cast to a `TlvType`.
91 *
92 * @returns A `TlvType` reference to `aTlv`.
93 */
As(NetworkDataTlv & aTlv)94 template <class TlvType> TlvType &As(NetworkDataTlv &aTlv) { return static_cast<TlvType &>(aTlv); }
95
96 /**
97 * 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 */
As(const NetworkDataTlv & aTlv)105 template <class TlvType> const TlvType &As(const NetworkDataTlv &aTlv) { return static_cast<const TlvType &>(aTlv); }
106
107 /**
108 * Implements Thread Network Data TLV generation and parsing.
109 */
110 OT_TOOL_PACKED_BEGIN
111 class NetworkDataTlv
112 {
113 public:
114 /**
115 * Thread Network Data Type values.
116 */
117 enum Type : uint8_t
118 {
119 kTypeHasRoute = 0, ///< Has Route TLV
120 kTypePrefix = 1, ///< Prefix TLV
121 kTypeBorderRouter = 2, ///< Border Router TLV
122 kTypeContext = 3, ///< Context TLV
123 kTypeCommissioningData = 4, ///< Commissioning Dataset TLV
124 kTypeService = 5, ///< Service TLV
125 kTypeServer = 6, ///< Server TLV
126 };
127
128 /**
129 * Initializes the TLV.
130 */
Init(void)131 void Init(void)
132 {
133 mType = 0;
134 mLength = 0;
135 }
136
137 /**
138 * Returns the Type value.
139 *
140 * @returns The Type value.
141 */
GetType(void) const142 Type GetType(void) const { return static_cast<Type>(mType >> kTypeOffset); }
143
144 /**
145 * Sets the Type value.
146 *
147 * @param[in] aType The Type value.
148 */
SetType(Type aType)149 void SetType(Type aType) { mType = (mType & ~kTypeMask) | ((aType << kTypeOffset) & kTypeMask); }
150
151 /**
152 * Returns the Length value.
153 *
154 * @returns The Length value.
155 */
GetLength(void) const156 uint8_t GetLength(void) const { return mLength; }
157
158 /**
159 * Sets the Length value.
160 *
161 * @param[in] aLength The Length value.
162 */
SetLength(uint8_t aLength)163 void SetLength(uint8_t aLength) { mLength = aLength; }
164
165 /**
166 * Increases the Length value by a given amount.
167 *
168 * @param[in] aIncrement The increment amount to increase the length.
169 */
IncreaseLength(uint8_t aIncrement)170 void IncreaseLength(uint8_t aIncrement) { mLength += aIncrement; }
171
172 /**
173 * Decreases the Length value by a given amount.
174 *
175 * @param[in] aDecrement The decrement amount to decrease the length.
176 */
DecreaseLength(uint8_t aDecrement)177 void DecreaseLength(uint8_t aDecrement) { mLength -= aDecrement; }
178
179 /**
180 * Returns the TLV's total size (number of bytes) including Type, Length, and Value fields.
181 *
182 * @returns The total size include Type, Length, and Value fields.
183 */
GetSize(void) const184 uint8_t GetSize(void) const { return sizeof(NetworkDataTlv) + mLength; }
185
186 /**
187 * Returns a pointer to the Value.
188 *
189 * @returns A pointer to the value.
190 */
GetValue(void)191 uint8_t *GetValue(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(NetworkDataTlv); }
192
193 /**
194 * Returns a pointer to the Value.
195 *
196 * @returns A pointer to the value.
197 */
GetValue(void) const198 const uint8_t *GetValue(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(NetworkDataTlv); }
199
200 /**
201 * Returns a pointer to the next Network Data TLV.
202 *
203 * @returns A pointer to the next Network Data TLV.
204 */
GetNext(void)205 NetworkDataTlv *GetNext(void)
206 {
207 return reinterpret_cast<NetworkDataTlv *>(reinterpret_cast<uint8_t *>(this) + sizeof(*this) + mLength);
208 }
209
210 /**
211 * Returns a pointer to the next Network Data TLV.
212 *
213 * @returns A pointer to the next Network Data TLV.
214 */
GetNext(void) const215 const NetworkDataTlv *GetNext(void) const
216 {
217 return reinterpret_cast<const NetworkDataTlv *>(reinterpret_cast<const uint8_t *>(this) + sizeof(*this) +
218 mLength);
219 }
220
221 /**
222 * Clears the Stable bit.
223 */
ClearStable(void)224 void ClearStable(void) { mType &= ~kStableMask; }
225
226 /**
227 * Indicates whether or not the Stable bit is set.
228 *
229 * @retval TRUE If the Stable bit is set.
230 * @retval FALSE If the Stable bit is not set.
231 */
IsStable(void) const232 bool IsStable(void) const { return (mType & kStableMask); }
233
234 /**
235 * Sets the Stable bit.
236 */
SetStable(void)237 void SetStable(void) { mType |= kStableMask; }
238
239 /**
240 * Searches in a given sequence of TLVs to find the first TLV with a given type.
241 *
242 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
243 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
244 * @param[in] aType The TLV type to find.
245 *
246 * @returns A pointer to the TLV if found, or `nullptr` if not found.
247 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,Type aType)248 static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType)
249 {
250 return AsNonConst(Find(AsConst(aStart), AsConst(aEnd), aType));
251 }
252
253 /**
254 * Searches in a given sequence of TLVs to find the first TLV with a given type.
255 *
256 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
257 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
258 * @param[in] aType The TLV type to find.
259 *
260 * @returns A pointer to the TLV if found, or `nullptr` if not found.
261 */
262 static const NetworkDataTlv *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, Type aType);
263
264 /**
265 * This template static method searches in a given sequence of TLVs to find the first TLV with a given type.
266 *
267 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
268 *
269 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
270 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
271 *
272 * @returns A pointer to the TLV if found, or `nullptr` if not found.
273 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd)274 template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd)
275 {
276 return As<TlvType>(Find(aStart, aEnd, TlvType::kType));
277 }
278
279 /**
280 * This template static method searches in a given sequence of TLVs to find the first TLV with a given type.
281 *
282 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
283 *
284 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
285 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
286 *
287 * @returns A pointer to the TLV if found, or `nullptr` if not found.
288 */
Find(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)289 template <typename TlvType> static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
290 {
291 return As<TlvType>(Find(aStart, aEnd, TlvType::kType));
292 }
293
294 /**
295 * Searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable
296 * flag.
297 *
298 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
299 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
300 * @param[in] aType The TLV type to find.
301 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
302 *
303 * @returns A pointer to the TLV if found, or `nullptr` if not found.
304 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,Type aType,bool aStable)305 static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType, bool aStable)
306 {
307 return AsNonConst(Find(AsConst(aStart), AsConst(aEnd), aType, aStable));
308 }
309
310 /**
311 * Searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable
312 * flag.
313 *
314 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
315 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
316 * @param[in] aType The TLV type to find.
317 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
318 *
319 * @returns A pointer to the TLV if found, or `nullptr` if not found.
320 */
321 static const NetworkDataTlv *Find(const NetworkDataTlv *aStart,
322 const NetworkDataTlv *aEnd,
323 Type aType,
324 bool aStable);
325
326 /**
327 * This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and
328 * stable flag.
329 *
330 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
331 *
332 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
333 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
334 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
335 *
336 * @returns A pointer to the TLV if found, or `nullptr` if not found.
337 */
Find(NetworkDataTlv * aStart,NetworkDataTlv * aEnd,bool aStable)338 template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable)
339 {
340 return As<TlvType>(Find(aStart, aEnd, TlvType::kType, aStable));
341 }
342
343 /**
344 * This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and
345 * stable flag.
346 *
347 * @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
348 *
349 * @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
350 * @param[in] aEnd A pointer to the end of the sequence of TLVs.
351 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
352 *
353 * @returns A pointer to the TLV if found, or `nullptr` if not found.
354 */
355 template <typename TlvType>
Find(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd,bool aStable)356 static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, bool aStable)
357 {
358 return As<TlvType>(Find(aStart, aEnd, TlvType::kType, aStable));
359 }
360
361 private:
362 static constexpr uint8_t kTypeOffset = 1;
363 static constexpr uint8_t kTypeMask = 0x7f << kTypeOffset;
364 static constexpr uint8_t kStableMask = 1 << 0;
365
366 uint8_t mType;
367 uint8_t mLength;
368 } OT_TOOL_PACKED_END;
369
370 /**
371 * Implements Has Route TLV entry generation and parsing.
372 */
373 OT_TOOL_PACKED_BEGIN
374 class HasRouteEntry : public Equatable<HasRouteEntry>
375 {
376 friend class ExternalRouteConfig;
377
378 public:
379 /**
380 * Initializes the header.
381 */
Init(void)382 void Init(void)
383 {
384 SetRloc(Mle::kInvalidRloc16);
385 mFlags = 0;
386 }
387
388 /**
389 * Returns the RLOC16 value.
390 *
391 * @returns The RLOC16 value.
392 */
GetRloc(void) const393 uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
394
395 /**
396 * Sets the RLOC16 value.
397 *
398 * @param[in] aRloc16 The RLOC16 value.
399 */
SetRloc(uint16_t aRloc16)400 void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
401
402 /**
403 * Returns the Preference value.
404 *
405 * @returns The preference value.
406 */
GetPreference(void) const407 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
408
409 /**
410 * Gets the Flags value.
411 *
412 * @returns The Flags value.
413 */
GetFlags(void) const414 uint8_t GetFlags(void) const { return mFlags; }
415
416 /**
417 * Sets the Flags value.
418 *
419 * @param[in] aFlags The Flags value.
420 */
SetFlags(uint8_t aFlags)421 void SetFlags(uint8_t aFlags) { mFlags = aFlags; }
422
423 /**
424 * Indicates whether or not the NAT64 flag is set.
425 *
426 * @retval TRUE If the NAT64 flag is set.
427 * @retval FALSE If the NAT64 flag is not set.
428 */
IsNat64(void) const429 bool IsNat64(void) const { return (mFlags & kNat64Flag) != 0; }
430
431 /**
432 * Indicates whether or not the Advertising PIO (AP) flag is set.
433 *
434 * @retval TRUE If the AP flag is set.
435 * @retval FALSE If the AP flag is not set.
436 */
IsAdvPio(void) const437 bool IsAdvPio(void) const { return (mFlags & kAdvPioFlag) != 0; }
438
439 /**
440 * Returns a pointer to the next HasRouteEntry.
441 *
442 * @returns A pointer to the next HasRouteEntry.
443 */
GetNext(void)444 HasRouteEntry *GetNext(void) { return (this + 1); }
445
446 /**
447 * Returns a pointer to the next HasRouteEntry.
448 *
449 * @returns A pointer to the next HasRouteEntry.
450 */
GetNext(void) const451 const HasRouteEntry *GetNext(void) const { return (this + 1); }
452
453 /**
454 * Returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
455 * given flags bitmask.
456 *
457 * @param[in] aFlags The flags bitmask.
458 *
459 * @returns An updated version @p aFlags with preference bits cleared.
460 */
FlagsWithoutPreference(uint8_t aFlags)461 static uint8_t FlagsWithoutPreference(uint8_t aFlags) { return (aFlags & ~kPreferenceMask); }
462
463 /**
464 * Gets the preference field from a flags bitmask.
465 *
466 * @param[in] aFlags The flags.
467 *
468 * @returns The preference field from the @p aFlags.
469 */
PreferenceFromFlags(uint8_t aFlags)470 static int8_t PreferenceFromFlags(uint8_t aFlags) { return RoutePreferenceFromValue(aFlags >> kPreferenceOffset); }
471
472 private:
473 static constexpr uint8_t kPreferenceOffset = 6;
474 static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
475 static constexpr uint8_t kNat64Flag = 1 << 5;
476 static constexpr uint8_t kAdvPioFlag = 1 << 4;
477
478 uint16_t mRloc;
479 uint8_t mFlags;
480 } OT_TOOL_PACKED_END;
481
482 /**
483 * Implements Has Route TLV generation and parsing.
484 */
485 OT_TOOL_PACKED_BEGIN
486 class HasRouteTlv : public NetworkDataTlv
487 {
488 public:
489 static constexpr Type kType = kTypeHasRoute; ///< The TLV Type.
490
491 /**
492 * Initializes the TLV.
493 */
Init(void)494 void Init(void)
495 {
496 NetworkDataTlv::Init();
497 SetType(kTypeHasRoute);
498 SetLength(0);
499 }
500
501 /**
502 * Returns the number of HasRoute entries.
503 *
504 * @returns The number of HasRoute entries.
505 */
GetNumEntries(void) const506 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(HasRouteEntry); }
507
508 /**
509 * Returns a pointer to the HasRoute entry at a given index.
510 *
511 * @param[in] aIndex An index.
512 *
513 * @returns A pointer to the HasRoute entry at @p aIndex.
514 */
GetEntry(uint8_t aIndex)515 HasRouteEntry *GetEntry(uint8_t aIndex)
516 {
517 return reinterpret_cast<HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry)));
518 }
519
520 /**
521 * Returns a pointer to the HasRoute entry at a given index.
522 *
523 * @param[in] aIndex An index.
524 *
525 * @returns A pointer to the HasRoute entry at @p aIndex.
526 */
GetEntry(uint8_t aIndex) const527 const HasRouteEntry *GetEntry(uint8_t aIndex) const
528 {
529 return reinterpret_cast<const HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry)));
530 }
531
532 /**
533 * Returns a pointer to the first HasRouteEntry (at index 0'th).
534 *
535 * @returns A pointer to the first HasRouteEntry.
536 */
GetFirstEntry(void)537 HasRouteEntry *GetFirstEntry(void) { return reinterpret_cast<HasRouteEntry *>(GetValue()); }
538
539 /**
540 * Returns a pointer to the first HasRouteEntry (at index 0'th).
541 *
542 * @returns A pointer to the first HasRouteEntry.
543 */
GetFirstEntry(void) const544 const HasRouteEntry *GetFirstEntry(void) const { return reinterpret_cast<const HasRouteEntry *>(GetValue()); }
545
546 /**
547 * Returns a pointer to the last HasRouteEntry.
548 *
549 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
550 *
551 * @returns A pointer to the last HasRouteEntry.
552 */
GetLastEntry(void)553 HasRouteEntry *GetLastEntry(void)
554 {
555 return reinterpret_cast<HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry));
556 }
557
558 /**
559 * Returns a pointer to the last HasRouteEntry.
560 *
561 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
562 *
563 * @returns A pointer to the last HasRouteEntry.
564 */
GetLastEntry(void) const565 const HasRouteEntry *GetLastEntry(void) const
566 {
567 return reinterpret_cast<const HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry));
568 }
569
570 } OT_TOOL_PACKED_END;
571
572 /**
573 * Implements Prefix TLV generation and parsing.
574 */
575 OT_TOOL_PACKED_BEGIN
576 class PrefixTlv : public NetworkDataTlv
577 {
578 public:
579 static constexpr Type kType = kTypePrefix; ///< The TLV Type.
580
581 /**
582 * Initializes the TLV.
583 *
584 * @param[in] aDomainId The Domain ID.
585 * @param[in] aPrefixLength The Prefix Length in bits.
586 * @param[in] aPrefix A pointer to the prefix.
587 */
Init(uint8_t aDomainId,uint8_t aPrefixLength,const uint8_t * aPrefix)588 void Init(uint8_t aDomainId, uint8_t aPrefixLength, const uint8_t *aPrefix)
589 {
590 NetworkDataTlv::Init();
591 SetType(kTypePrefix);
592 mDomainId = aDomainId;
593 mPrefixLength = aPrefixLength;
594 memcpy(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength));
595 SetSubTlvsLength(0);
596 }
597
598 /**
599 * Initializes the TLV.
600 *
601 * @param[in] aDomainId The Domain ID.
602 * @param[in] aPrefix The Prefix.
603 */
Init(uint8_t aDomainId,const Ip6::Prefix aPrefix)604 void Init(uint8_t aDomainId, const Ip6::Prefix aPrefix)
605 {
606 Init(aDomainId, aPrefix.GetLength(), aPrefix.GetBytes());
607 }
608
609 /**
610 * Indicates whether or not the TLV appears to be well-formed.
611 *
612 * @retval TRUE If the TLV appears to be well-formed.
613 * @retval FALSE If the TLV does not appear to be well-formed.
614 */
IsValid(void) const615 bool IsValid(void) const
616 {
617 return ((GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv)) &&
618 (GetLength() >= Ip6::Prefix::SizeForLength(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv)) &&
619 (Ip6::Prefix::SizeForLength(mPrefixLength) <= sizeof(Ip6::Address)));
620 }
621
622 /**
623 * Returns the Domain ID value.
624 *
625 * @returns The Domain ID value.
626 */
GetDomainId(void) const627 uint8_t GetDomainId(void) const { return mDomainId; }
628
629 /**
630 * Returns the Prefix Length value.
631 *
632 * @returns The Prefix Length value (in bits).
633 */
GetPrefixLength(void) const634 uint8_t GetPrefixLength(void) const { return mPrefixLength; }
635
636 /**
637 * Returns a pointer to the Prefix.
638 *
639 * @returns A pointer to the Prefix.
640 */
GetPrefix(void)641 uint8_t *GetPrefix(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
642
643 /**
644 * Returns a pointer to the Prefix.
645 *
646 * @returns A pointer to the Prefix.
647 */
GetPrefix(void) const648 const uint8_t *GetPrefix(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
649
650 /**
651 * Copies the Prefix from TLV into a given `Ip6::Prefix`.
652 *
653 * @param[out] aPrefix An `Ip6::Prefix` to copy the Prefix from TLV into.
654 */
CopyPrefixTo(Ip6::Prefix & aPrefix) const655 void CopyPrefixTo(Ip6::Prefix &aPrefix) const { aPrefix.Set(GetPrefix(), GetPrefixLength()); }
656
657 /**
658 * Indicates whether the Prefix from TLV is equal to a given `Ip6::Prefix`.
659 *
660 * @param[in] aPrefix A Prefix to compare with.
661 *
662 * @retval TRUE The TLV's Prefix is equal to @p aPrefix.
663 * @retval FALSE The TLV's Prefix is not equal to @p aPrefix.
664 */
IsEqual(Ip6::Prefix & aPrefix) const665 bool IsEqual(Ip6::Prefix &aPrefix) const { return aPrefix.IsEqual(GetPrefix(), GetPrefixLength()); }
666
667 /**
668 * Indicates whether the Prefix from TLV is equal to a given Prefix.
669 *
670 * @param[in] aPrefix A pointer to an IPv6 prefix to compare with.
671 * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits).
672 *
673 * @retval TRUE The TLV's Prefix is equal to @p aPrefix.
674 * @retval FALSE The TLV's Prefix is not equal @p aPrefix.
675 */
IsEqual(const uint8_t * aPrefix,uint8_t aPrefixLength) const676 bool IsEqual(const uint8_t *aPrefix, uint8_t aPrefixLength) const
677 {
678 return (aPrefixLength == mPrefixLength) &&
679 (Ip6::Prefix::MatchLength(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)) >=
680 mPrefixLength);
681 }
682
683 /**
684 * Returns a pointer to the Sub-TLVs.
685 *
686 * @returns A pointer to the Sub-TLVs.
687 */
GetSubTlvs(void)688 NetworkDataTlv *GetSubTlvs(void)
689 {
690 return reinterpret_cast<NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength));
691 }
692
693 /**
694 * Returns a pointer to the Sub-TLVs.
695 *
696 * @returns A pointer to the Sub-TLVs.
697 */
GetSubTlvs(void) const698 const NetworkDataTlv *GetSubTlvs(void) const
699 {
700 return reinterpret_cast<const NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength));
701 }
702
703 /**
704 * Returns the Sub-TLVs length in bytes.
705 *
706 * @returns The Sub-TLVs length in bytes.
707 */
GetSubTlvsLength(void) const708 uint8_t GetSubTlvsLength(void) const
709 {
710 return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength));
711 }
712
713 /**
714 * Sets the Sub-TLVs length in bytes.
715 *
716 * @param[in] aLength The Sub-TLVs length in bytes.
717 */
SetSubTlvsLength(uint8_t aLength)718 void SetSubTlvsLength(uint8_t aLength)
719 {
720 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength) + aLength);
721 }
722
723 /**
724 * Searches in the sub-TLVs to find the first one matching a given TLV type.
725 *
726 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
727 *
728 * @returns A pointer to the TLV if found, or `nullptr` if not found.
729 */
FindSubTlv(void)730 template <typename SubTlvType> SubTlvType *FindSubTlv(void)
731 {
732 return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
733 }
734
735 /**
736 * Searches in the sub-TLVs to find the first one matching a given TLV Type.
737 *
738 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
739 *
740 * @returns A pointer to the TLV if found, or `nullptr` if not found.
741 */
FindSubTlv(void) const742 template <typename SubTlvType> const SubTlvType *FindSubTlv(void) const
743 {
744 return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
745 }
746
747 /**
748 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
749 *
750 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
751 *
752 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
753 *
754 * @returns A pointer to the TLV if found, or `nullptr` if not found.
755 */
FindSubTlv(bool aStable)756 template <typename SubTlvType> SubTlvType *FindSubTlv(bool aStable)
757 {
758 return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
759 }
760
761 /**
762 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
763 *
764 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
765 *
766 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
767 *
768 * @returns A pointer to the TLV if found, or `nullptr` if not found.
769 */
FindSubTlv(bool aStable) const770 template <typename SubTlvType> const SubTlvType *FindSubTlv(bool aStable) const
771 {
772 return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
773 }
774
775 /**
776 * Searches in the sub-TLVs to find the first one matching a given TLV type.
777 *
778 * @param[in] aType The sub-TLV type to search for.
779 *
780 * @returns A pointer to the TLV if found, or `nullptr` if not found.
781 */
FindSubTlv(Type aType)782 NetworkDataTlv *FindSubTlv(Type aType) { return AsNonConst(AsConst(this)->FindSubTlv(aType)); }
783
784 /**
785 * Searches in the sub-TLVs to find the first one matching a given TLV type.
786 *
787 * @param[in] aType The sub-TLV type to search for.
788 *
789 * @returns A pointer to the TLV if found, or `nullptr` if not found.
790 */
791 const NetworkDataTlv *FindSubTlv(Type aType) const;
792
793 /**
794 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
795 *
796 * @param[in] aType The sub-TLV type to search for.
797 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
798 *
799 * @returns A pointer to the TLV if found, or `nullptr` if not found.
800 */
FindSubTlv(Type aType,bool aStable)801 NetworkDataTlv *FindSubTlv(Type aType, bool aStable)
802 {
803 return AsNonConst(AsConst(this)->FindSubTlv(aType, aStable));
804 }
805
806 /**
807 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
808 *
809 * @param[in] aType The sub-TLV type to search for.
810 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
811 *
812 * @returns A pointer to the TLV if found, or `nullptr` if not found.
813 */
814 const NetworkDataTlv *FindSubTlv(Type aType, bool aStable) const;
815
816 /**
817 * Calculates the total size (number of bytes) of a Prefix TLV with a given Prefix Length value.
818 *
819 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any
820 * sub TLVs of the Prefix TLV.
821 *
822 * @param[in] aPrefixLength A Prefix Length in bits.
823
824 * @returns The size (number of bytes) of the Prefix TLV.
825 */
CalculateSize(uint8_t aPrefixLength)826 static uint16_t CalculateSize(uint8_t aPrefixLength)
827 {
828 return sizeof(PrefixTlv) + Ip6::Prefix::SizeForLength(aPrefixLength);
829 }
830
831 private:
832 uint8_t mDomainId;
833 uint8_t mPrefixLength;
834 } OT_TOOL_PACKED_END;
835
836 /**
837 * Implements Border Router Entry generation and parsing.
838 */
839 OT_TOOL_PACKED_BEGIN
840 class BorderRouterEntry : public Equatable<BorderRouterEntry>
841 {
842 friend class OnMeshPrefixConfig;
843
844 public:
845 /**
846 * Initializes the TLV.
847 */
Init(void)848 void Init(void)
849 {
850 SetRloc(Mle::kInvalidRloc16);
851 mFlags = 0;
852 }
853
854 /**
855 * Returns the RLOC16 value.
856 *
857 * @returns The RLOC16 value.
858 */
GetRloc(void) const859 uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
860
861 /**
862 * Sets the RLOC16 value.
863 *
864 * @param[in] aRloc16 The RLOC16 value.
865 */
SetRloc(uint16_t aRloc16)866 void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
867
868 /**
869 * Returns the Flags value.
870 *
871 * @returns The Flags value.
872 */
GetFlags(void) const873 uint16_t GetFlags(void) const { return BigEndian::HostSwap16(mFlags); }
874
875 /**
876 * Sets the Flags value.
877 *
878 * @param[in] aFlags The Flags value.
879 */
SetFlags(uint16_t aFlags)880 void SetFlags(uint16_t aFlags) { mFlags = BigEndian::HostSwap16(aFlags); }
881
882 /**
883 * Returns the Preference value.
884 *
885 * @returns the Preference value.
886 */
GetPreference(void) const887 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
888
889 /**
890 * Indicates whether or not the Preferred flag is set.
891 *
892 * @retval TRUE If the Preferred flag is set.
893 * @retval FALSE If the Preferred flag is not set.
894 */
IsPreferred(void) const895 bool IsPreferred(void) const { return (BigEndian::HostSwap16(mFlags) & kPreferredFlag) != 0; }
896
897 /**
898 * Indicates whether or not the SLAAC flag is set.
899 *
900 * @retval TRUE If the SLAAC flag is set.
901 * @retval FALSE If the SLAAC flag is not set.
902 */
IsSlaac(void) const903 bool IsSlaac(void) const { return (BigEndian::HostSwap16(mFlags) & kSlaacFlag) != 0; }
904
905 /**
906 * Indicates whether or not the DHCP flag is set.
907 *
908 * @retval TRUE If the DHCP flag is set.
909 * @retval FALSE If the DHCP flag is not set.
910 */
IsDhcp(void) const911 bool IsDhcp(void) const { return (BigEndian::HostSwap16(mFlags) & kDhcpFlag) != 0; }
912
913 /**
914 * Indicates whether or not the Configure flag is set.
915 *
916 * @retval TRUE If the Configure flag is set.
917 * @retval FALSE If the Configure flag is not set.
918 */
IsConfigure(void) const919 bool IsConfigure(void) const { return (BigEndian::HostSwap16(mFlags) & kConfigureFlag) != 0; }
920
921 /**
922 * Indicates whether or not the Default Route flag is set.
923 *
924 * @retval TRUE If the Default Route flag is set.
925 * @retval FALSE If the Default Route flag is not set.
926 */
IsDefaultRoute(void) const927 bool IsDefaultRoute(void) const { return (BigEndian::HostSwap16(mFlags) & kDefaultRouteFlag) != 0; }
928
929 /**
930 * Indicates whether or not the On-Mesh flag is set.
931 *
932 * @retval TRUE If the On-Mesh flag is set.
933 * @retval FALSE If the On-Mesh flag is not set.
934 */
IsOnMesh(void) const935 bool IsOnMesh(void) const { return (BigEndian::HostSwap16(mFlags) & kOnMeshFlag) != 0; }
936
937 /**
938 * Indicates whether or not the Nd-Dns flag is set.
939 *
940 * @retval TRUE If the Nd-Dns flag is set.
941 * @retval FALSE If the Nd-Dns flag is not set.
942 */
IsNdDns(void) const943 bool IsNdDns(void) const { return (BigEndian::HostSwap16(mFlags) & kNdDnsFlag) != 0; }
944
945 /**
946 * Indicates whether or not the Domain Prefix flag is set.
947 *
948 * @retval TRUE If the Domain Prefix flag is set.
949 * @retval FALSE If the Domain Prefix flag is not set.
950 */
IsDp(void) const951 bool IsDp(void) const { return (BigEndian::HostSwap16(mFlags) & kDpFlag) != 0; }
952
953 /**
954 * Returns a pointer to the next BorderRouterEntry
955 *
956 * @returns A pointer to the next BorderRouterEntry.
957 */
GetNext(void)958 BorderRouterEntry *GetNext(void) { return (this + 1); }
959
960 /**
961 * Returns a pointer to the next BorderRouterEntry
962 *
963 * @returns A pointer to the next BorderRouterEntry.
964 */
GetNext(void) const965 const BorderRouterEntry *GetNext(void) const { return (this + 1); }
966
967 /**
968 * Returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
969 * given flags bitmask.
970 *
971 * @param[in] aFlags The flags bitmask.
972 *
973 * @returns An updated version @p aFlags with preference bits cleared.
974 */
FlagsWithoutPreference(uint16_t aFlags)975 static uint16_t FlagsWithoutPreference(uint16_t aFlags) { return (aFlags & ~kPreferenceMask); }
976
977 /**
978 * Gets the preference field from a flags bitmask.
979 *
980 * @param[in] aFlags The flags.
981 *
982 * @returns The preference field from the @p aFlags.
983 */
PreferenceFromFlags(uint16_t aFlags)984 static int8_t PreferenceFromFlags(uint16_t aFlags)
985 {
986 return RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> kPreferenceOffset));
987 }
988
989 private:
990 static constexpr uint8_t kPreferenceOffset = 14;
991 static constexpr uint16_t kPreferenceMask = 3 << kPreferenceOffset;
992 static constexpr uint16_t kPreferredFlag = 1 << 13;
993 static constexpr uint16_t kSlaacFlag = 1 << 12;
994 static constexpr uint16_t kDhcpFlag = 1 << 11;
995 static constexpr uint16_t kConfigureFlag = 1 << 10;
996 static constexpr uint16_t kDefaultRouteFlag = 1 << 9;
997 static constexpr uint16_t kOnMeshFlag = 1 << 8;
998 static constexpr uint16_t kNdDnsFlag = 1 << 7;
999 static constexpr uint16_t kDpFlag = 1 << 6;
1000
1001 uint16_t mRloc;
1002 uint16_t mFlags;
1003 } OT_TOOL_PACKED_END;
1004
1005 /**
1006 * Implements Border Router TLV generation and parsing.
1007 */
1008 OT_TOOL_PACKED_BEGIN
1009 class BorderRouterTlv : public NetworkDataTlv
1010 {
1011 public:
1012 static constexpr Type kType = kTypeBorderRouter; ///< The TLV Type.
1013
1014 /**
1015 * Initializes the TLV.
1016 */
Init(void)1017 void Init(void)
1018 {
1019 NetworkDataTlv::Init();
1020 SetType(kTypeBorderRouter);
1021 SetLength(0);
1022 }
1023
1024 /**
1025 * Returns the number of Border Router entries.
1026 *
1027 * @returns The number of Border Router entries.
1028 */
GetNumEntries(void) const1029 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(BorderRouterEntry); }
1030
1031 /**
1032 * Returns a pointer to the Border Router entry at a given index
1033 *
1034 * @param[in] aIndex The index.
1035 *
1036 * @returns A pointer to the Border Router entry at @p aIndex.
1037 */
GetEntry(uint8_t aIndex)1038 BorderRouterEntry *GetEntry(uint8_t aIndex)
1039 {
1040 return reinterpret_cast<BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry)));
1041 }
1042
1043 /**
1044 * Returns a pointer to the Border Router entry at a given index.
1045 *
1046 * @param[in] aIndex The index.
1047 *
1048 * @returns A pointer to the Border Router entry at @p aIndex
1049 */
GetEntry(uint8_t aIndex) const1050 const BorderRouterEntry *GetEntry(uint8_t aIndex) const
1051 {
1052 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry)));
1053 }
1054
1055 /**
1056 * Returns a pointer to the first BorderRouterEntry (at index 0'th).
1057 *
1058 * @returns A pointer to the first BorderRouterEntry.
1059 */
GetFirstEntry(void)1060 BorderRouterEntry *GetFirstEntry(void) { return reinterpret_cast<BorderRouterEntry *>(GetValue()); }
1061
1062 /**
1063 * Returns a pointer to the first BorderRouterEntry (at index 0'th).
1064 *
1065 * @returns A pointer to the first BorderRouterEntry.
1066 */
GetFirstEntry(void) const1067 const BorderRouterEntry *GetFirstEntry(void) const
1068 {
1069 return reinterpret_cast<const BorderRouterEntry *>(GetValue());
1070 }
1071
1072 /**
1073 * Returns a pointer to the last BorderRouterEntry.
1074 *
1075 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
1076 *
1077 * @returns A pointer to the last BorderRouterEntry.
1078 */
GetLastEntry(void)1079 BorderRouterEntry *GetLastEntry(void)
1080 {
1081 return reinterpret_cast<BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry));
1082 }
1083
1084 /**
1085 * Returns a pointer to the last BorderRouterEntry.
1086 *
1087 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
1088 *
1089 * @returns A pointer to the last BorderRouterEntry.
1090 */
GetLastEntry(void) const1091 const BorderRouterEntry *GetLastEntry(void) const
1092 {
1093 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry));
1094 }
1095
1096 } OT_TOOL_PACKED_END;
1097
1098 /**
1099 * Implements Context TLV generation and processing.
1100 */
1101 OT_TOOL_PACKED_BEGIN
1102 class ContextTlv : public NetworkDataTlv
1103 {
1104 public:
1105 static constexpr Type kType = kTypeContext; ///< The TLV Type.
1106
1107 /**
1108 * Initializes the Context TLV.
1109 *
1110 * @param[in] aContextId The Context ID value.
1111 * @param[in] aContextLength The Context Length value.
1112 */
Init(uint8_t aContextId,uint8_t aContextLength)1113 void Init(uint8_t aContextId, uint8_t aContextLength)
1114 {
1115 NetworkDataTlv::Init();
1116 SetType(kTypeContext);
1117 SetLength(sizeof(ContextTlv) - sizeof(NetworkDataTlv));
1118 mFlags = ((aContextId << kContextIdOffset) & kContextIdMask);
1119 mContextLength = aContextLength;
1120 }
1121
1122 /**
1123 * Indicates whether or not the Compress flag is set.
1124 *
1125 * @retval TRUE The Compress flag is set.
1126 * @retval FALSE The Compress flags is not set.
1127 */
IsCompress(void) const1128 bool IsCompress(void) const { return (mFlags & kCompressFlag) != 0; }
1129
1130 /**
1131 * Clears the Compress flag.
1132 */
ClearCompress(void)1133 void ClearCompress(void) { mFlags &= ~kCompressFlag; }
1134
1135 /**
1136 * Sets the Compress flag.
1137 */
SetCompress(void)1138 void SetCompress(void) { mFlags |= kCompressFlag; }
1139
1140 /**
1141 * Returns the Context ID value.
1142 *
1143 * @returns The Context ID value.
1144 */
GetContextId(void) const1145 uint8_t GetContextId(void) const { return mFlags & kContextIdMask; }
1146
1147 /**
1148 * Returns the Context Length value.
1149 *
1150 * @returns The Context Length value.
1151 */
GetContextLength(void) const1152 uint8_t GetContextLength(void) const { return mContextLength; }
1153
1154 private:
1155 static constexpr uint8_t kCompressFlag = 1 << 4;
1156 static constexpr uint8_t kContextIdOffset = 0;
1157 static constexpr uint8_t kContextIdMask = 0xf << kContextIdOffset;
1158
1159 uint8_t mFlags;
1160 uint8_t mContextLength;
1161 } OT_TOOL_PACKED_END;
1162
1163 /**
1164 * Implements Commissioning Data TLV generation and parsing.
1165 */
1166 OT_TOOL_PACKED_BEGIN
1167 class CommissioningDataTlv : public NetworkDataTlv
1168 {
1169 public:
1170 static constexpr Type kType = kTypeCommissioningData; ///< The TLV Type.
1171
1172 /**
1173 * Initializes the TLV.
1174 */
Init(void)1175 void Init(void)
1176 {
1177 NetworkDataTlv::Init();
1178 SetType(kTypeCommissioningData);
1179 SetLength(0);
1180 }
1181 } OT_TOOL_PACKED_END;
1182
1183 /**
1184 * Implements Service Data TLV generation and parsing.
1185 */
1186 OT_TOOL_PACKED_BEGIN
1187 class ServiceTlv : public NetworkDataTlv
1188 {
1189 public:
1190 static constexpr Type kType = kTypeService; ///< The TLV Type.
1191
1192 static constexpr uint32_t kThreadEnterpriseNumber = 44970; ///< Thread enterprise number.
1193
1194 /**
1195 * Initializes the TLV.
1196 *
1197 * @param[in] aServiceId The Service Id value.
1198 * @param[in] aEnterpriseNumber The Enterprise Number.
1199 * @param[in] aServiceData The Service Data.
1200 */
1201 void Init(uint8_t aServiceId, uint32_t aEnterpriseNumber, const ServiceData &aServiceData);
1202
1203 /**
1204 * Indicates whether or not the TLV appears to be well-formed.
1205 *
1206 * @retval TRUE If the TLV appears to be well-formed.
1207 * @retval FALSE If the TLV does not appear to be well-formed.
1208 */
IsValid(void) const1209 bool IsValid(void) const
1210 {
1211 uint8_t length = GetLength();
1212
1213 return (length >= sizeof(mFlagsServiceId)) &&
1214 (length >= kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t))) &&
1215 (static_cast<uint16_t>(length) + sizeof(NetworkDataTlv) >=
1216 CalculateSize(GetEnterpriseNumber(), GetServiceDataLength()));
1217 }
1218
1219 /**
1220 * Returns the Service ID. It is in range 0x00-0x0f.
1221 *
1222 * @returns the Service ID.
1223 */
GetServiceId(void) const1224 uint8_t GetServiceId(void) const { return (mFlagsServiceId & kServiceIdMask); }
1225
1226 /**
1227 * Returns Enterprise Number field.
1228 *
1229 * @returns The Enterprise Number.
1230 */
GetEnterpriseNumber(void) const1231 uint32_t GetEnterpriseNumber(void) const
1232 {
1233 return IsThreadEnterprise() ? static_cast<uint32_t>(kThreadEnterpriseNumber)
1234 : BigEndian::HostSwap32(mShared.mEnterpriseNumber);
1235 }
1236
1237 /**
1238 * Gets the Service Data.
1239 *
1240 * @param[out] aServiceData A reference to a`ServiceData` to return the data.
1241 */
GetServiceData(ServiceData & aServiceData) const1242 void GetServiceData(ServiceData &aServiceData) const
1243 {
1244 aServiceData.Init(GetServiceData(), GetServiceDataLength());
1245 }
1246
1247 /**
1248 * Gets the Service Data bytes.
1249 *
1250 * @returns A pointer to start of the Service Data bytes.
1251 */
GetServiceData(void) const1252 const uint8_t *GetServiceData(void) const
1253 {
1254 return (IsThreadEnterprise() ? &mShared.mServiceDataLengthThreadEnterprise : &mServiceDataLength) +
1255 sizeof(uint8_t);
1256 }
1257
1258 /**
1259 * Gets Service Data length.
1260 *
1261 * @returns length of the Service Data field in bytes.
1262 */
GetServiceDataLength(void) const1263 uint8_t GetServiceDataLength(void) const
1264 {
1265 return IsThreadEnterprise() ? mShared.mServiceDataLengthThreadEnterprise : mServiceDataLength;
1266 }
1267
1268 /**
1269 * Returns the Sub-TLVs length in bytes.
1270 *
1271 * @returns The Sub-TLVs length in bytes.
1272 */
GetSubTlvsLength(void)1273 uint8_t GetSubTlvsLength(void) { return GetLength() - GetFieldsLength(); }
1274
1275 /**
1276 * Sets the Sub-TLVs length in bytes.
1277 *
1278 * @param[in] aLength The Sub-TLVs length in bytes.
1279 */
SetSubTlvsLength(uint8_t aLength)1280 void SetSubTlvsLength(uint8_t aLength) { SetLength(GetFieldsLength() + aLength); }
1281
1282 /**
1283 * Returns a pointer to the Sub-TLVs.
1284 *
1285 * @returns A pointer to the Sub-TLVs.
1286 */
GetSubTlvs(void)1287 NetworkDataTlv *GetSubTlvs(void) { return reinterpret_cast<NetworkDataTlv *>(GetValue() + GetFieldsLength()); }
1288
1289 /**
1290 * Returns a pointer to the Sub-TLVs.
1291 *
1292 * @returns A pointer to the Sub-TLVs.
1293 */
GetSubTlvs(void) const1294 const NetworkDataTlv *GetSubTlvs(void) const
1295 {
1296 return reinterpret_cast<const NetworkDataTlv *>(GetValue() + GetFieldsLength());
1297 }
1298
1299 /**
1300 * Calculates the total size (number of bytes) of a Service TLV with a given Enterprise Number
1301 * and Service Data length.
1302 *
1303 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any
1304 * sub-TLVs of the Service TLV.
1305 *
1306 * @param[in] aEnterpriseNumber A Enterprise Number.
1307 * @param[in] aServiceDataLength A Service Data length.
1308 *
1309 * @returns The size (number of bytes) of the Service TLV.
1310 */
CalculateSize(uint32_t aEnterpriseNumber,uint8_t aServiceDataLength)1311 static uint16_t CalculateSize(uint32_t aEnterpriseNumber, uint8_t aServiceDataLength)
1312 {
1313 return sizeof(NetworkDataTlv) + kMinLength + aServiceDataLength +
1314 ((aEnterpriseNumber == kThreadEnterpriseNumber) ? 0 : sizeof(uint32_t) /* mEnterpriseNumber */);
1315 }
1316
1317 private:
IsThreadEnterprise(void) const1318 bool IsThreadEnterprise(void) const { return (mFlagsServiceId & kThreadEnterpriseFlag) != 0; }
1319
GetFieldsLength(void) const1320 uint8_t GetFieldsLength(void) const
1321 {
1322 // Returns the length of TLV value's common fields (flags, enterprise
1323 // number and service data) excluding any sub-TLVs.
1324
1325 return kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t)) + GetServiceDataLength();
1326 }
1327
1328 static constexpr uint8_t kThreadEnterpriseFlag = (1 << 7);
1329 static constexpr uint8_t kServiceIdMask = 0xf;
1330 static constexpr uint8_t kMinLength = sizeof(uint8_t) + sizeof(uint8_t); // Flags & Service Data length.
1331
1332 // When `kThreadEnterpriseFlag is set in the `mFlagsServiceId`, the
1333 // `mEnterpriseNumber` field is elided and `mFlagsServiceId` is
1334 // immediately followed by the Service Data length field (which is
1335 // represented by `mServiceDataLengthThreadEnterprise`)
1336
1337 uint8_t mFlagsServiceId;
1338 union OT_TOOL_PACKED_FIELD
1339 {
1340 uint32_t mEnterpriseNumber;
1341 uint8_t mServiceDataLengthThreadEnterprise;
1342 } mShared;
1343 uint8_t mServiceDataLength;
1344
1345 } OT_TOOL_PACKED_END;
1346
1347 /**
1348 * Implements Server Data TLV generation and parsing.
1349 */
1350 OT_TOOL_PACKED_BEGIN
1351 class ServerTlv : public NetworkDataTlv
1352 {
1353 public:
1354 static constexpr Type kType = kTypeServer; ///< The TLV Type.
1355
1356 /**
1357 * Initializes the Server TLV.
1358 *
1359 * @param[in] aServer16 The Server16 value.
1360 * @param[in] aServerData The Server Data.
1361 */
Init(uint16_t aServer16,const ServerData & aServerData)1362 void Init(uint16_t aServer16, const ServerData &aServerData)
1363 {
1364 NetworkDataTlv::Init();
1365 SetType(kTypeServer);
1366 SetServer16(aServer16);
1367 aServerData.CopyBytesTo(GetServerData());
1368 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + aServerData.GetLength());
1369 }
1370
1371 /**
1372 * Indicates whether or not the TLV appears to be well-formed.
1373 *
1374 * @retval TRUE If the TLV appears to be well-formed.
1375 * @retval FALSE If the TLV does not appear to be well-formed.
1376 */
IsValid(void) const1377 bool IsValid(void) const { return GetLength() >= (sizeof(*this) - sizeof(NetworkDataTlv)); }
1378
1379 /**
1380 * Returns the Server16 value.
1381 *
1382 * @returns The Server16 value.
1383 */
GetServer16(void) const1384 uint16_t GetServer16(void) const { return BigEndian::HostSwap16(mServer16); }
1385
1386 /*
1387 * Sets the Server16 value.
1388 *
1389 * @param[in] aServer16 The Server16 value.
1390 */
SetServer16(uint16_t aServer16)1391 void SetServer16(uint16_t aServer16) { mServer16 = BigEndian::HostSwap16(aServer16); }
1392
1393 /**
1394 * Gets the Server Data.
1395 *
1396 * @param[out] aServerData A reference to a`ServerData` to return the data.
1397 */
GetServerData(ServerData & aServerData) const1398 void GetServerData(ServerData &aServerData) const { aServerData.Init(GetServerData(), GetServerDataLength()); }
1399
1400 /**
1401 * Gets the Server Data bytes.
1402 *
1403 * @returns A pointer to start of the Server Data bytes.
1404 */
GetServerData(void) const1405 const uint8_t *GetServerData(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
1406
1407 /**
1408 * Returns the Server Data length in bytes.
1409 *
1410 * @returns The Server Data length in bytes.
1411 */
GetServerDataLength(void) const1412 uint8_t GetServerDataLength(void) const { return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv)); }
1413
1414 /**
1415 * Indicates whether two Server TLVs fully match.
1416 *
1417 * @param[in] aOther Another Server TLV to compare with it.
1418 *
1419 * @retval TRUE The two TLVs are equal.
1420 * @retval FALSE The two TLVs are not equal.
1421 */
operator ==(const ServerTlv & aOther) const1422 bool operator==(const ServerTlv &aOther) const
1423 {
1424 return (GetLength() == aOther.GetLength()) && (memcmp(GetValue(), aOther.GetValue(), GetLength()) == 0);
1425 }
1426
1427 /**
1428 * Calculates the total size (number of bytes) of a Service TLV with a given Server Data length.
1429 *
1430 * Note that the returned size does include the Type and Length fields in the TLV.
1431 *
1432 * @param[in] aServerDataLength Server Data length in bytes.
1433 *
1434 * @returns The size (number of bytes) of the Server TLV.
1435 */
CalculateSize(uint8_t aServerDataLength)1436 static uint16_t CalculateSize(uint8_t aServerDataLength) { return sizeof(ServerTlv) + aServerDataLength; }
1437
1438 private:
GetServerData(void)1439 uint8_t *GetServerData(void) { return AsNonConst(AsConst(this)->GetServerData()); }
1440
1441 uint16_t mServer16;
1442 } OT_TOOL_PACKED_END;
1443
1444 /**
1445 * Represents a Network Data TLV iterator.
1446 */
1447 class TlvIterator
1448 {
1449 public:
1450 /**
1451 * Initializes the `TlvIterator` to iterate over a given sequence of TLVs.
1452 *
1453 * @param[in] aStart A pointer to the start of the TLV sequence.
1454 * @param[in] aEnd A pointer to the end of the TLV sequence.
1455 */
TlvIterator(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)1456 TlvIterator(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
1457 : mStart(aStart)
1458 , mEnd(aEnd)
1459 {
1460 }
1461
1462 /**
1463 * Initializes the `TlvIterator` to iterate over TLVs from a given buffer.
1464 *
1465 * @param[in] aBuffer A pointer to a buffer containing the TLVs.
1466 * @param[in] aLength The length (number of bytes) of @p aBuffer.
1467 */
TlvIterator(const uint8_t * aBuffer,uint8_t aLength)1468 TlvIterator(const uint8_t *aBuffer, uint8_t aLength)
1469 : TlvIterator(reinterpret_cast<const NetworkDataTlv *>(aBuffer),
1470 reinterpret_cast<const NetworkDataTlv *>(aBuffer + aLength))
1471 {
1472 }
1473
1474 /**
1475 * Initializes the `TlvIterator` to iterate over sub-TLVs of a given Prefix TLV.
1476 *
1477 * @param[in] aPrefixTlv A Prefix TLV to iterate over its sub-TLVs.
1478 */
TlvIterator(const PrefixTlv & aPrefixTlv)1479 explicit TlvIterator(const PrefixTlv &aPrefixTlv)
1480 : TlvIterator(aPrefixTlv.GetSubTlvs(), aPrefixTlv.GetNext())
1481 {
1482 }
1483
1484 /**
1485 * Initializes the `TlvIterator` to iterate over sub-TLVs of a given Service TLV.
1486 *
1487 * @param[in] aServiceTlv A Service TLV to iterate over its sub-TLVs.
1488 */
TlvIterator(const ServiceTlv & aServiceTlv)1489 explicit TlvIterator(const ServiceTlv &aServiceTlv)
1490 : TlvIterator(aServiceTlv.GetSubTlvs(), aServiceTlv.GetNext())
1491 {
1492 }
1493
1494 /**
1495 * Iterates to the next TLV with a given type.
1496 *
1497 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
1498 *
1499 * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
1500 */
Iterate(void)1501 template <typename TlvType> const TlvType *Iterate(void) { return As<TlvType>(Iterate(TlvType::kType)); }
1502
1503 /**
1504 * Iterates to the next TLV with a given type and stable flag.
1505 *
1506 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
1507 *
1508 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
1509 *
1510 * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
1511 */
Iterate(bool aStable)1512 template <typename TlvType> const TlvType *Iterate(bool aStable)
1513 {
1514 return As<TlvType>(Iterate(TlvType::kType, aStable));
1515 }
1516
1517 private:
1518 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType);
1519 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType, bool aStable);
1520
1521 const NetworkDataTlv *mStart;
1522 const NetworkDataTlv *mEnd;
1523 };
1524
1525 /**
1526 * @}
1527 */
1528
1529 } // namespace NetworkData
1530 } // namespace ot
1531
1532 #endif // NETWORK_DATA_TLVS_HPP_
1533