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 static bool IsTlvValid(const NetworkDataTlv *aTlv);
367
368 uint8_t mType;
369 uint8_t mLength;
370 } OT_TOOL_PACKED_END;
371
372 /**
373 * Implements Has Route TLV entry generation and parsing.
374 */
375 OT_TOOL_PACKED_BEGIN
376 class HasRouteEntry : public Equatable<HasRouteEntry>
377 {
378 friend class ExternalRouteConfig;
379
380 public:
381 /**
382 * Initializes the header.
383 */
Init(void)384 void Init(void)
385 {
386 SetRloc(Mle::kInvalidRloc16);
387 mFlags = 0;
388 }
389
390 /**
391 * Returns the RLOC16 value.
392 *
393 * @returns The RLOC16 value.
394 */
GetRloc(void) const395 uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
396
397 /**
398 * Sets the RLOC16 value.
399 *
400 * @param[in] aRloc16 The RLOC16 value.
401 */
SetRloc(uint16_t aRloc16)402 void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
403
404 /**
405 * Returns the Preference value.
406 *
407 * @returns The preference value.
408 */
GetPreference(void) const409 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
410
411 /**
412 * Gets the Flags value.
413 *
414 * @returns The Flags value.
415 */
GetFlags(void) const416 uint8_t GetFlags(void) const { return mFlags; }
417
418 /**
419 * Sets the Flags value.
420 *
421 * @param[in] aFlags The Flags value.
422 */
SetFlags(uint8_t aFlags)423 void SetFlags(uint8_t aFlags) { mFlags = aFlags; }
424
425 /**
426 * Indicates whether or not the NAT64 flag is set.
427 *
428 * @retval TRUE If the NAT64 flag is set.
429 * @retval FALSE If the NAT64 flag is not set.
430 */
IsNat64(void) const431 bool IsNat64(void) const { return (mFlags & kNat64Flag) != 0; }
432
433 /**
434 * Indicates whether or not the Advertising PIO (AP) flag is set.
435 *
436 * @retval TRUE If the AP flag is set.
437 * @retval FALSE If the AP flag is not set.
438 */
IsAdvPio(void) const439 bool IsAdvPio(void) const { return (mFlags & kAdvPioFlag) != 0; }
440
441 /**
442 * Returns a pointer to the next HasRouteEntry.
443 *
444 * @returns A pointer to the next HasRouteEntry.
445 */
GetNext(void)446 HasRouteEntry *GetNext(void) { return (this + 1); }
447
448 /**
449 * Returns a pointer to the next HasRouteEntry.
450 *
451 * @returns A pointer to the next HasRouteEntry.
452 */
GetNext(void) const453 const HasRouteEntry *GetNext(void) const { return (this + 1); }
454
455 /**
456 * Returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
457 * given flags bitmask.
458 *
459 * @param[in] aFlags The flags bitmask.
460 *
461 * @returns An updated version @p aFlags with preference bits cleared.
462 */
FlagsWithoutPreference(uint8_t aFlags)463 static uint8_t FlagsWithoutPreference(uint8_t aFlags) { return (aFlags & ~kPreferenceMask); }
464
465 /**
466 * Gets the preference field from a flags bitmask.
467 *
468 * @param[in] aFlags The flags.
469 *
470 * @returns The preference field from the @p aFlags.
471 */
PreferenceFromFlags(uint8_t aFlags)472 static int8_t PreferenceFromFlags(uint8_t aFlags) { return RoutePreferenceFromValue(aFlags >> kPreferenceOffset); }
473
474 private:
475 static constexpr uint8_t kPreferenceOffset = 6;
476 static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
477 static constexpr uint8_t kNat64Flag = 1 << 5;
478 static constexpr uint8_t kAdvPioFlag = 1 << 4;
479
480 uint16_t mRloc;
481 uint8_t mFlags;
482 } OT_TOOL_PACKED_END;
483
484 /**
485 * Implements Has Route TLV generation and parsing.
486 */
487 OT_TOOL_PACKED_BEGIN
488 class HasRouteTlv : public NetworkDataTlv
489 {
490 public:
491 static constexpr Type kType = kTypeHasRoute; ///< The TLV Type.
492
493 /**
494 * Initializes the TLV.
495 */
Init(void)496 void Init(void)
497 {
498 NetworkDataTlv::Init();
499 SetType(kTypeHasRoute);
500 SetLength(0);
501 }
502
503 /**
504 * Returns the number of HasRoute entries.
505 *
506 * @returns The number of HasRoute entries.
507 */
GetNumEntries(void) const508 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(HasRouteEntry); }
509
510 /**
511 * Returns a pointer to the HasRoute entry at a given index.
512 *
513 * @param[in] aIndex An index.
514 *
515 * @returns A pointer to the HasRoute entry at @p aIndex.
516 */
GetEntry(uint8_t aIndex)517 HasRouteEntry *GetEntry(uint8_t aIndex)
518 {
519 return reinterpret_cast<HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry)));
520 }
521
522 /**
523 * Returns a pointer to the HasRoute entry at a given index.
524 *
525 * @param[in] aIndex An index.
526 *
527 * @returns A pointer to the HasRoute entry at @p aIndex.
528 */
GetEntry(uint8_t aIndex) const529 const HasRouteEntry *GetEntry(uint8_t aIndex) const
530 {
531 return reinterpret_cast<const HasRouteEntry *>(GetValue() + (aIndex * sizeof(HasRouteEntry)));
532 }
533
534 /**
535 * Returns a pointer to the first HasRouteEntry (at index 0'th).
536 *
537 * @returns A pointer to the first HasRouteEntry.
538 */
GetFirstEntry(void)539 HasRouteEntry *GetFirstEntry(void) { return reinterpret_cast<HasRouteEntry *>(GetValue()); }
540
541 /**
542 * Returns a pointer to the first HasRouteEntry (at index 0'th).
543 *
544 * @returns A pointer to the first HasRouteEntry.
545 */
GetFirstEntry(void) const546 const HasRouteEntry *GetFirstEntry(void) const { return reinterpret_cast<const HasRouteEntry *>(GetValue()); }
547
548 /**
549 * Returns a pointer to the last HasRouteEntry.
550 *
551 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
552 *
553 * @returns A pointer to the last HasRouteEntry.
554 */
GetLastEntry(void)555 HasRouteEntry *GetLastEntry(void)
556 {
557 return reinterpret_cast<HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry));
558 }
559
560 /**
561 * Returns a pointer to the last HasRouteEntry.
562 *
563 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
564 *
565 * @returns A pointer to the last HasRouteEntry.
566 */
GetLastEntry(void) const567 const HasRouteEntry *GetLastEntry(void) const
568 {
569 return reinterpret_cast<const HasRouteEntry *>(GetValue() + GetLength() - sizeof(HasRouteEntry));
570 }
571
572 } OT_TOOL_PACKED_END;
573
574 /**
575 * Implements Prefix TLV generation and parsing.
576 */
577 OT_TOOL_PACKED_BEGIN
578 class PrefixTlv : public NetworkDataTlv
579 {
580 public:
581 static constexpr Type kType = kTypePrefix; ///< The TLV Type.
582
583 /**
584 * Initializes the TLV.
585 *
586 * @param[in] aDomainId The Domain ID.
587 * @param[in] aPrefixLength The Prefix Length in bits.
588 * @param[in] aPrefix A pointer to the prefix.
589 */
Init(uint8_t aDomainId,uint8_t aPrefixLength,const uint8_t * aPrefix)590 void Init(uint8_t aDomainId, uint8_t aPrefixLength, const uint8_t *aPrefix)
591 {
592 NetworkDataTlv::Init();
593 SetType(kTypePrefix);
594 mDomainId = aDomainId;
595 mPrefixLength = aPrefixLength;
596 memcpy(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength));
597 SetSubTlvsLength(0);
598 }
599
600 /**
601 * Initializes the TLV.
602 *
603 * @param[in] aDomainId The Domain ID.
604 * @param[in] aPrefix The Prefix.
605 */
Init(uint8_t aDomainId,const Ip6::Prefix aPrefix)606 void Init(uint8_t aDomainId, const Ip6::Prefix aPrefix)
607 {
608 Init(aDomainId, aPrefix.GetLength(), aPrefix.GetBytes());
609 }
610
611 /**
612 * Indicates whether or not the TLV appears to be well-formed.
613 *
614 * @retval TRUE If the TLV appears to be well-formed.
615 * @retval FALSE If the TLV does not appear to be well-formed.
616 */
IsValid(void) const617 bool IsValid(void) const
618 {
619 return ((GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv)) &&
620 (GetLength() >= Ip6::Prefix::SizeForLength(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv)) &&
621 (Ip6::Prefix::SizeForLength(mPrefixLength) <= sizeof(Ip6::Address)));
622 }
623
624 /**
625 * Returns the Domain ID value.
626 *
627 * @returns The Domain ID value.
628 */
GetDomainId(void) const629 uint8_t GetDomainId(void) const { return mDomainId; }
630
631 /**
632 * Returns the Prefix Length value.
633 *
634 * @returns The Prefix Length value (in bits).
635 */
GetPrefixLength(void) const636 uint8_t GetPrefixLength(void) const { return mPrefixLength; }
637
638 /**
639 * Returns a pointer to the Prefix.
640 *
641 * @returns A pointer to the Prefix.
642 */
GetPrefix(void)643 uint8_t *GetPrefix(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
644
645 /**
646 * Returns a pointer to the Prefix.
647 *
648 * @returns A pointer to the Prefix.
649 */
GetPrefix(void) const650 const uint8_t *GetPrefix(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
651
652 /**
653 * Copies the Prefix from TLV into a given `Ip6::Prefix`.
654 *
655 * @param[out] aPrefix An `Ip6::Prefix` to copy the Prefix from TLV into.
656 */
CopyPrefixTo(Ip6::Prefix & aPrefix) const657 void CopyPrefixTo(Ip6::Prefix &aPrefix) const { aPrefix.Set(GetPrefix(), GetPrefixLength()); }
658
659 /**
660 * Indicates whether the Prefix from TLV is equal to a given `Ip6::Prefix`.
661 *
662 * @param[in] aPrefix A Prefix to compare with.
663 *
664 * @retval TRUE The TLV's Prefix is equal to @p aPrefix.
665 * @retval FALSE The TLV's Prefix is not equal to @p aPrefix.
666 */
IsEqual(Ip6::Prefix & aPrefix) const667 bool IsEqual(Ip6::Prefix &aPrefix) const { return aPrefix.IsEqual(GetPrefix(), GetPrefixLength()); }
668
669 /**
670 * Indicates whether the Prefix from TLV is equal to a given Prefix.
671 *
672 * @param[in] aPrefix A pointer to an IPv6 prefix to compare with.
673 * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits).
674 *
675 * @retval TRUE The TLV's Prefix is equal to @p aPrefix.
676 * @retval FALSE The TLV's Prefix is not equal @p aPrefix.
677 */
IsEqual(const uint8_t * aPrefix,uint8_t aPrefixLength) const678 bool IsEqual(const uint8_t *aPrefix, uint8_t aPrefixLength) const
679 {
680 return (aPrefixLength == mPrefixLength) &&
681 (Ip6::Prefix::MatchLength(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)) >=
682 mPrefixLength);
683 }
684
685 /**
686 * Returns a pointer to the Sub-TLVs.
687 *
688 * @returns A pointer to the Sub-TLVs.
689 */
GetSubTlvs(void)690 NetworkDataTlv *GetSubTlvs(void)
691 {
692 return reinterpret_cast<NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength));
693 }
694
695 /**
696 * Returns a pointer to the Sub-TLVs.
697 *
698 * @returns A pointer to the Sub-TLVs.
699 */
GetSubTlvs(void) const700 const NetworkDataTlv *GetSubTlvs(void) const
701 {
702 return reinterpret_cast<const NetworkDataTlv *>(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength));
703 }
704
705 /**
706 * Returns the Sub-TLVs length in bytes.
707 *
708 * @returns The Sub-TLVs length in bytes.
709 */
GetSubTlvsLength(void) const710 uint8_t GetSubTlvsLength(void) const
711 {
712 return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength));
713 }
714
715 /**
716 * Sets the Sub-TLVs length in bytes.
717 *
718 * @param[in] aLength The Sub-TLVs length in bytes.
719 */
SetSubTlvsLength(uint8_t aLength)720 void SetSubTlvsLength(uint8_t aLength)
721 {
722 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength) + aLength);
723 }
724
725 /**
726 * Searches in the sub-TLVs to find the first one matching a given TLV type.
727 *
728 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
729 *
730 * @returns A pointer to the TLV if found, or `nullptr` if not found.
731 */
FindSubTlv(void)732 template <typename SubTlvType> SubTlvType *FindSubTlv(void)
733 {
734 return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
735 }
736
737 /**
738 * Searches in the sub-TLVs to find the first one matching a given TLV Type.
739 *
740 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
741 *
742 * @returns A pointer to the TLV if found, or `nullptr` if not found.
743 */
FindSubTlv(void) const744 template <typename SubTlvType> const SubTlvType *FindSubTlv(void) const
745 {
746 return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
747 }
748
749 /**
750 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
751 *
752 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
753 *
754 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
755 *
756 * @returns A pointer to the TLV if found, or `nullptr` if not found.
757 */
FindSubTlv(bool aStable)758 template <typename SubTlvType> SubTlvType *FindSubTlv(bool aStable)
759 {
760 return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
761 }
762
763 /**
764 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
765 *
766 * @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
767 *
768 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
769 *
770 * @returns A pointer to the TLV if found, or `nullptr` if not found.
771 */
FindSubTlv(bool aStable) const772 template <typename SubTlvType> const SubTlvType *FindSubTlv(bool aStable) const
773 {
774 return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
775 }
776
777 /**
778 * Searches in the sub-TLVs to find the first one matching a given TLV type.
779 *
780 * @param[in] aType The sub-TLV type to search for.
781 *
782 * @returns A pointer to the TLV if found, or `nullptr` if not found.
783 */
FindSubTlv(Type aType)784 NetworkDataTlv *FindSubTlv(Type aType) { return AsNonConst(AsConst(this)->FindSubTlv(aType)); }
785
786 /**
787 * Searches in the sub-TLVs to find the first one matching a given TLV type.
788 *
789 * @param[in] aType The sub-TLV type to search for.
790 *
791 * @returns A pointer to the TLV if found, or `nullptr` if not found.
792 */
793 const NetworkDataTlv *FindSubTlv(Type aType) const;
794
795 /**
796 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
797 *
798 * @param[in] aType The sub-TLV type to search for.
799 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
800 *
801 * @returns A pointer to the TLV if found, or `nullptr` if not found.
802 */
FindSubTlv(Type aType,bool aStable)803 NetworkDataTlv *FindSubTlv(Type aType, bool aStable)
804 {
805 return AsNonConst(AsConst(this)->FindSubTlv(aType, aStable));
806 }
807
808 /**
809 * Searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
810 *
811 * @param[in] aType The sub-TLV type to search for.
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 const NetworkDataTlv *FindSubTlv(Type aType, bool aStable) const;
817
818 /**
819 * Calculates the total size (number of bytes) of a Prefix TLV with a given Prefix Length value.
820 *
821 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any
822 * sub TLVs of the Prefix TLV.
823 *
824 * @param[in] aPrefixLength A Prefix Length in bits.
825
826 * @returns The size (number of bytes) of the Prefix TLV.
827 */
CalculateSize(uint8_t aPrefixLength)828 static uint16_t CalculateSize(uint8_t aPrefixLength)
829 {
830 return sizeof(PrefixTlv) + Ip6::Prefix::SizeForLength(aPrefixLength);
831 }
832
833 private:
834 uint8_t mDomainId;
835 uint8_t mPrefixLength;
836 } OT_TOOL_PACKED_END;
837
838 /**
839 * Implements Border Router Entry generation and parsing.
840 */
841 OT_TOOL_PACKED_BEGIN
842 class BorderRouterEntry : public Equatable<BorderRouterEntry>
843 {
844 friend class OnMeshPrefixConfig;
845
846 public:
847 /**
848 * Initializes the TLV.
849 */
Init(void)850 void Init(void)
851 {
852 SetRloc(Mle::kInvalidRloc16);
853 mFlags = 0;
854 }
855
856 /**
857 * Returns the RLOC16 value.
858 *
859 * @returns The RLOC16 value.
860 */
GetRloc(void) const861 uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
862
863 /**
864 * Sets the RLOC16 value.
865 *
866 * @param[in] aRloc16 The RLOC16 value.
867 */
SetRloc(uint16_t aRloc16)868 void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
869
870 /**
871 * Returns the Flags value.
872 *
873 * @returns The Flags value.
874 */
GetFlags(void) const875 uint16_t GetFlags(void) const { return BigEndian::HostSwap16(mFlags); }
876
877 /**
878 * Sets the Flags value.
879 *
880 * @param[in] aFlags The Flags value.
881 */
SetFlags(uint16_t aFlags)882 void SetFlags(uint16_t aFlags) { mFlags = BigEndian::HostSwap16(aFlags); }
883
884 /**
885 * Returns the Preference value.
886 *
887 * @returns the Preference value.
888 */
GetPreference(void) const889 int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
890
891 /**
892 * Indicates whether or not the Preferred flag is set.
893 *
894 * @retval TRUE If the Preferred flag is set.
895 * @retval FALSE If the Preferred flag is not set.
896 */
IsPreferred(void) const897 bool IsPreferred(void) const { return (BigEndian::HostSwap16(mFlags) & kPreferredFlag) != 0; }
898
899 /**
900 * Indicates whether or not the SLAAC flag is set.
901 *
902 * @retval TRUE If the SLAAC flag is set.
903 * @retval FALSE If the SLAAC flag is not set.
904 */
IsSlaac(void) const905 bool IsSlaac(void) const { return (BigEndian::HostSwap16(mFlags) & kSlaacFlag) != 0; }
906
907 /**
908 * Indicates whether or not the DHCP flag is set.
909 *
910 * @retval TRUE If the DHCP flag is set.
911 * @retval FALSE If the DHCP flag is not set.
912 */
IsDhcp(void) const913 bool IsDhcp(void) const { return (BigEndian::HostSwap16(mFlags) & kDhcpFlag) != 0; }
914
915 /**
916 * Indicates whether or not the Configure flag is set.
917 *
918 * @retval TRUE If the Configure flag is set.
919 * @retval FALSE If the Configure flag is not set.
920 */
IsConfigure(void) const921 bool IsConfigure(void) const { return (BigEndian::HostSwap16(mFlags) & kConfigureFlag) != 0; }
922
923 /**
924 * Indicates whether or not the Default Route flag is set.
925 *
926 * @retval TRUE If the Default Route flag is set.
927 * @retval FALSE If the Default Route flag is not set.
928 */
IsDefaultRoute(void) const929 bool IsDefaultRoute(void) const { return (BigEndian::HostSwap16(mFlags) & kDefaultRouteFlag) != 0; }
930
931 /**
932 * Indicates whether or not the On-Mesh flag is set.
933 *
934 * @retval TRUE If the On-Mesh flag is set.
935 * @retval FALSE If the On-Mesh flag is not set.
936 */
IsOnMesh(void) const937 bool IsOnMesh(void) const { return (BigEndian::HostSwap16(mFlags) & kOnMeshFlag) != 0; }
938
939 /**
940 * Indicates whether or not the Nd-Dns flag is set.
941 *
942 * @retval TRUE If the Nd-Dns flag is set.
943 * @retval FALSE If the Nd-Dns flag is not set.
944 */
IsNdDns(void) const945 bool IsNdDns(void) const { return (BigEndian::HostSwap16(mFlags) & kNdDnsFlag) != 0; }
946
947 /**
948 * Indicates whether or not the Domain Prefix flag is set.
949 *
950 * @retval TRUE If the Domain Prefix flag is set.
951 * @retval FALSE If the Domain Prefix flag is not set.
952 */
IsDp(void) const953 bool IsDp(void) const { return (BigEndian::HostSwap16(mFlags) & kDpFlag) != 0; }
954
955 /**
956 * Returns a pointer to the next BorderRouterEntry
957 *
958 * @returns A pointer to the next BorderRouterEntry.
959 */
GetNext(void)960 BorderRouterEntry *GetNext(void) { return (this + 1); }
961
962 /**
963 * Returns a pointer to the next BorderRouterEntry
964 *
965 * @returns A pointer to the next BorderRouterEntry.
966 */
GetNext(void) const967 const BorderRouterEntry *GetNext(void) const { return (this + 1); }
968
969 /**
970 * Returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
971 * given flags bitmask.
972 *
973 * @param[in] aFlags The flags bitmask.
974 *
975 * @returns An updated version @p aFlags with preference bits cleared.
976 */
FlagsWithoutPreference(uint16_t aFlags)977 static uint16_t FlagsWithoutPreference(uint16_t aFlags) { return (aFlags & ~kPreferenceMask); }
978
979 /**
980 * Gets the preference field from a flags bitmask.
981 *
982 * @param[in] aFlags The flags.
983 *
984 * @returns The preference field from the @p aFlags.
985 */
PreferenceFromFlags(uint16_t aFlags)986 static int8_t PreferenceFromFlags(uint16_t aFlags)
987 {
988 return RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> kPreferenceOffset));
989 }
990
991 private:
992 static constexpr uint8_t kPreferenceOffset = 14;
993 static constexpr uint16_t kPreferenceMask = 3 << kPreferenceOffset;
994 static constexpr uint16_t kPreferredFlag = 1 << 13;
995 static constexpr uint16_t kSlaacFlag = 1 << 12;
996 static constexpr uint16_t kDhcpFlag = 1 << 11;
997 static constexpr uint16_t kConfigureFlag = 1 << 10;
998 static constexpr uint16_t kDefaultRouteFlag = 1 << 9;
999 static constexpr uint16_t kOnMeshFlag = 1 << 8;
1000 static constexpr uint16_t kNdDnsFlag = 1 << 7;
1001 static constexpr uint16_t kDpFlag = 1 << 6;
1002
1003 uint16_t mRloc;
1004 uint16_t mFlags;
1005 } OT_TOOL_PACKED_END;
1006
1007 /**
1008 * Implements Border Router TLV generation and parsing.
1009 */
1010 OT_TOOL_PACKED_BEGIN
1011 class BorderRouterTlv : public NetworkDataTlv
1012 {
1013 public:
1014 static constexpr Type kType = kTypeBorderRouter; ///< The TLV Type.
1015
1016 /**
1017 * Initializes the TLV.
1018 */
Init(void)1019 void Init(void)
1020 {
1021 NetworkDataTlv::Init();
1022 SetType(kTypeBorderRouter);
1023 SetLength(0);
1024 }
1025
1026 /**
1027 * Returns the number of Border Router entries.
1028 *
1029 * @returns The number of Border Router entries.
1030 */
GetNumEntries(void) const1031 uint8_t GetNumEntries(void) const { return GetLength() / sizeof(BorderRouterEntry); }
1032
1033 /**
1034 * Returns a pointer to the Border Router entry at a given index
1035 *
1036 * @param[in] aIndex The index.
1037 *
1038 * @returns A pointer to the Border Router entry at @p aIndex.
1039 */
GetEntry(uint8_t aIndex)1040 BorderRouterEntry *GetEntry(uint8_t aIndex)
1041 {
1042 return reinterpret_cast<BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry)));
1043 }
1044
1045 /**
1046 * Returns a pointer to the Border Router entry at a given index.
1047 *
1048 * @param[in] aIndex The index.
1049 *
1050 * @returns A pointer to the Border Router entry at @p aIndex
1051 */
GetEntry(uint8_t aIndex) const1052 const BorderRouterEntry *GetEntry(uint8_t aIndex) const
1053 {
1054 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + (aIndex * sizeof(BorderRouterEntry)));
1055 }
1056
1057 /**
1058 * Returns a pointer to the first BorderRouterEntry (at index 0'th).
1059 *
1060 * @returns A pointer to the first BorderRouterEntry.
1061 */
GetFirstEntry(void)1062 BorderRouterEntry *GetFirstEntry(void) { return reinterpret_cast<BorderRouterEntry *>(GetValue()); }
1063
1064 /**
1065 * Returns a pointer to the first BorderRouterEntry (at index 0'th).
1066 *
1067 * @returns A pointer to the first BorderRouterEntry.
1068 */
GetFirstEntry(void) const1069 const BorderRouterEntry *GetFirstEntry(void) const
1070 {
1071 return reinterpret_cast<const BorderRouterEntry *>(GetValue());
1072 }
1073
1074 /**
1075 * Returns a pointer to the last BorderRouterEntry.
1076 *
1077 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
1078 *
1079 * @returns A pointer to the last BorderRouterEntry.
1080 */
GetLastEntry(void)1081 BorderRouterEntry *GetLastEntry(void)
1082 {
1083 return reinterpret_cast<BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry));
1084 }
1085
1086 /**
1087 * Returns a pointer to the last BorderRouterEntry.
1088 *
1089 * If there are no entries the pointer will be invalid but guaranteed to be before the `GetFirstEntry()` pointer.
1090 *
1091 * @returns A pointer to the last BorderRouterEntry.
1092 */
GetLastEntry(void) const1093 const BorderRouterEntry *GetLastEntry(void) const
1094 {
1095 return reinterpret_cast<const BorderRouterEntry *>(GetValue() + GetLength() - sizeof(BorderRouterEntry));
1096 }
1097
1098 } OT_TOOL_PACKED_END;
1099
1100 /**
1101 * Implements Context TLV generation and processing.
1102 */
1103 OT_TOOL_PACKED_BEGIN
1104 class ContextTlv : public NetworkDataTlv
1105 {
1106 public:
1107 static constexpr Type kType = kTypeContext; ///< The TLV Type.
1108
1109 /**
1110 * Initializes the Context TLV.
1111 *
1112 * @param[in] aContextId The Context ID value.
1113 * @param[in] aContextLength The Context Length value.
1114 */
Init(uint8_t aContextId,uint8_t aContextLength)1115 void Init(uint8_t aContextId, uint8_t aContextLength)
1116 {
1117 NetworkDataTlv::Init();
1118 SetType(kTypeContext);
1119 SetLength(sizeof(ContextTlv) - sizeof(NetworkDataTlv));
1120 mFlags = ((aContextId << kContextIdOffset) & kContextIdMask);
1121 mContextLength = aContextLength;
1122 }
1123
1124 /**
1125 * Indicates whether or not the TLV appears to be well-formed.
1126 *
1127 * @retval TRUE If the TLV appears to be well-formed.
1128 * @retval FALSE If the TLV does not appear to be well-formed.
1129 */
IsValid(void) const1130 bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv); }
1131
1132 /**
1133 * Indicates whether or not the Compress flag is set.
1134 *
1135 * @retval TRUE The Compress flag is set.
1136 * @retval FALSE The Compress flags is not set.
1137 */
IsCompress(void) const1138 bool IsCompress(void) const { return (mFlags & kCompressFlag) != 0; }
1139
1140 /**
1141 * Clears the Compress flag.
1142 */
ClearCompress(void)1143 void ClearCompress(void) { mFlags &= ~kCompressFlag; }
1144
1145 /**
1146 * Sets the Compress flag.
1147 */
SetCompress(void)1148 void SetCompress(void) { mFlags |= kCompressFlag; }
1149
1150 /**
1151 * Returns the Context ID value.
1152 *
1153 * @returns The Context ID value.
1154 */
GetContextId(void) const1155 uint8_t GetContextId(void) const { return mFlags & kContextIdMask; }
1156
1157 /**
1158 * Returns the Context Length value.
1159 *
1160 * @returns The Context Length value.
1161 */
GetContextLength(void) const1162 uint8_t GetContextLength(void) const { return mContextLength; }
1163
1164 private:
1165 static constexpr uint8_t kCompressFlag = 1 << 4;
1166 static constexpr uint8_t kContextIdOffset = 0;
1167 static constexpr uint8_t kContextIdMask = 0xf << kContextIdOffset;
1168
1169 uint8_t mFlags;
1170 uint8_t mContextLength;
1171 } OT_TOOL_PACKED_END;
1172
1173 /**
1174 * Implements Commissioning Data TLV generation and parsing.
1175 */
1176 OT_TOOL_PACKED_BEGIN
1177 class CommissioningDataTlv : public NetworkDataTlv
1178 {
1179 public:
1180 static constexpr Type kType = kTypeCommissioningData; ///< The TLV Type.
1181
1182 /**
1183 * Initializes the TLV.
1184 */
Init(void)1185 void Init(void)
1186 {
1187 NetworkDataTlv::Init();
1188 SetType(kTypeCommissioningData);
1189 SetLength(0);
1190 }
1191 } OT_TOOL_PACKED_END;
1192
1193 /**
1194 * Implements Service Data TLV generation and parsing.
1195 */
1196 OT_TOOL_PACKED_BEGIN
1197 class ServiceTlv : public NetworkDataTlv
1198 {
1199 public:
1200 static constexpr Type kType = kTypeService; ///< The TLV Type.
1201
1202 static constexpr uint32_t kThreadEnterpriseNumber = 44970; ///< Thread enterprise number.
1203
1204 /**
1205 * Initializes the TLV.
1206 *
1207 * @param[in] aServiceId The Service Id value.
1208 * @param[in] aEnterpriseNumber The Enterprise Number.
1209 * @param[in] aServiceData The Service Data.
1210 */
1211 void Init(uint8_t aServiceId, uint32_t aEnterpriseNumber, const ServiceData &aServiceData);
1212
1213 /**
1214 * Indicates whether or not the TLV appears to be well-formed.
1215 *
1216 * @retval TRUE If the TLV appears to be well-formed.
1217 * @retval FALSE If the TLV does not appear to be well-formed.
1218 */
IsValid(void) const1219 bool IsValid(void) const
1220 {
1221 uint8_t length = GetLength();
1222
1223 return (length >= sizeof(mFlagsServiceId)) &&
1224 (length >= kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t))) &&
1225 (static_cast<uint16_t>(length) + sizeof(NetworkDataTlv) >=
1226 CalculateSize(GetEnterpriseNumber(), GetServiceDataLength()));
1227 }
1228
1229 /**
1230 * Returns the Service ID. It is in range 0x00-0x0f.
1231 *
1232 * @returns the Service ID.
1233 */
GetServiceId(void) const1234 uint8_t GetServiceId(void) const { return (mFlagsServiceId & kServiceIdMask); }
1235
1236 /**
1237 * Returns Enterprise Number field.
1238 *
1239 * @returns The Enterprise Number.
1240 */
GetEnterpriseNumber(void) const1241 uint32_t GetEnterpriseNumber(void) const
1242 {
1243 return IsThreadEnterprise() ? static_cast<uint32_t>(kThreadEnterpriseNumber)
1244 : BigEndian::HostSwap32(mShared.mEnterpriseNumber);
1245 }
1246
1247 /**
1248 * Gets the Service Data.
1249 *
1250 * @param[out] aServiceData A reference to a`ServiceData` to return the data.
1251 */
GetServiceData(ServiceData & aServiceData) const1252 void GetServiceData(ServiceData &aServiceData) const
1253 {
1254 aServiceData.Init(GetServiceData(), GetServiceDataLength());
1255 }
1256
1257 /**
1258 * Gets the Service Data bytes.
1259 *
1260 * @returns A pointer to start of the Service Data bytes.
1261 */
GetServiceData(void) const1262 const uint8_t *GetServiceData(void) const
1263 {
1264 return (IsThreadEnterprise() ? &mShared.mServiceDataLengthThreadEnterprise : &mServiceDataLength) +
1265 sizeof(uint8_t);
1266 }
1267
1268 /**
1269 * Gets Service Data length.
1270 *
1271 * @returns length of the Service Data field in bytes.
1272 */
GetServiceDataLength(void) const1273 uint8_t GetServiceDataLength(void) const
1274 {
1275 return IsThreadEnterprise() ? mShared.mServiceDataLengthThreadEnterprise : mServiceDataLength;
1276 }
1277
1278 /**
1279 * Returns the Sub-TLVs length in bytes.
1280 *
1281 * @returns The Sub-TLVs length in bytes.
1282 */
GetSubTlvsLength(void)1283 uint8_t GetSubTlvsLength(void) { return GetLength() - GetFieldsLength(); }
1284
1285 /**
1286 * Sets the Sub-TLVs length in bytes.
1287 *
1288 * @param[in] aLength The Sub-TLVs length in bytes.
1289 */
SetSubTlvsLength(uint8_t aLength)1290 void SetSubTlvsLength(uint8_t aLength) { SetLength(GetFieldsLength() + aLength); }
1291
1292 /**
1293 * Returns a pointer to the Sub-TLVs.
1294 *
1295 * @returns A pointer to the Sub-TLVs.
1296 */
GetSubTlvs(void)1297 NetworkDataTlv *GetSubTlvs(void) { return reinterpret_cast<NetworkDataTlv *>(GetValue() + GetFieldsLength()); }
1298
1299 /**
1300 * Returns a pointer to the Sub-TLVs.
1301 *
1302 * @returns A pointer to the Sub-TLVs.
1303 */
GetSubTlvs(void) const1304 const NetworkDataTlv *GetSubTlvs(void) const
1305 {
1306 return reinterpret_cast<const NetworkDataTlv *>(GetValue() + GetFieldsLength());
1307 }
1308
1309 /**
1310 * Calculates the total size (number of bytes) of a Service TLV with a given Enterprise Number
1311 * and Service Data length.
1312 *
1313 * Note that the returned size does include the Type and Length fields in the TLV, but does not account for any
1314 * sub-TLVs of the Service TLV.
1315 *
1316 * @param[in] aEnterpriseNumber A Enterprise Number.
1317 * @param[in] aServiceDataLength A Service Data length.
1318 *
1319 * @returns The size (number of bytes) of the Service TLV.
1320 */
CalculateSize(uint32_t aEnterpriseNumber,uint8_t aServiceDataLength)1321 static uint16_t CalculateSize(uint32_t aEnterpriseNumber, uint8_t aServiceDataLength)
1322 {
1323 return sizeof(NetworkDataTlv) + kMinLength + aServiceDataLength +
1324 ((aEnterpriseNumber == kThreadEnterpriseNumber) ? 0 : sizeof(uint32_t) /* mEnterpriseNumber */);
1325 }
1326
1327 private:
IsThreadEnterprise(void) const1328 bool IsThreadEnterprise(void) const { return (mFlagsServiceId & kThreadEnterpriseFlag) != 0; }
1329
GetFieldsLength(void) const1330 uint8_t GetFieldsLength(void) const
1331 {
1332 // Returns the length of TLV value's common fields (flags, enterprise
1333 // number and service data) excluding any sub-TLVs.
1334
1335 return kMinLength + (IsThreadEnterprise() ? 0 : sizeof(uint32_t)) + GetServiceDataLength();
1336 }
1337
1338 static constexpr uint8_t kThreadEnterpriseFlag = (1 << 7);
1339 static constexpr uint8_t kServiceIdMask = 0xf;
1340 static constexpr uint8_t kMinLength = sizeof(uint8_t) + sizeof(uint8_t); // Flags & Service Data length.
1341
1342 // When `kThreadEnterpriseFlag is set in the `mFlagsServiceId`, the
1343 // `mEnterpriseNumber` field is elided and `mFlagsServiceId` is
1344 // immediately followed by the Service Data length field (which is
1345 // represented by `mServiceDataLengthThreadEnterprise`)
1346
1347 uint8_t mFlagsServiceId;
1348 union OT_TOOL_PACKED_FIELD
1349 {
1350 uint32_t mEnterpriseNumber;
1351 uint8_t mServiceDataLengthThreadEnterprise;
1352 } mShared;
1353 uint8_t mServiceDataLength;
1354
1355 } OT_TOOL_PACKED_END;
1356
1357 /**
1358 * Implements Server Data TLV generation and parsing.
1359 */
1360 OT_TOOL_PACKED_BEGIN
1361 class ServerTlv : public NetworkDataTlv
1362 {
1363 public:
1364 static constexpr Type kType = kTypeServer; ///< The TLV Type.
1365
1366 /**
1367 * Initializes the Server TLV.
1368 *
1369 * @param[in] aServer16 The Server16 value.
1370 * @param[in] aServerData The Server Data.
1371 */
Init(uint16_t aServer16,const ServerData & aServerData)1372 void Init(uint16_t aServer16, const ServerData &aServerData)
1373 {
1374 NetworkDataTlv::Init();
1375 SetType(kTypeServer);
1376 SetServer16(aServer16);
1377 aServerData.CopyBytesTo(GetServerData());
1378 SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + aServerData.GetLength());
1379 }
1380
1381 /**
1382 * Indicates whether or not the TLV appears to be well-formed.
1383 *
1384 * @retval TRUE If the TLV appears to be well-formed.
1385 * @retval FALSE If the TLV does not appear to be well-formed.
1386 */
IsValid(void) const1387 bool IsValid(void) const { return GetLength() >= (sizeof(*this) - sizeof(NetworkDataTlv)); }
1388
1389 /**
1390 * Returns the Server16 value.
1391 *
1392 * @returns The Server16 value.
1393 */
GetServer16(void) const1394 uint16_t GetServer16(void) const { return BigEndian::HostSwap16(mServer16); }
1395
1396 /*
1397 * Sets the Server16 value.
1398 *
1399 * @param[in] aServer16 The Server16 value.
1400 */
SetServer16(uint16_t aServer16)1401 void SetServer16(uint16_t aServer16) { mServer16 = BigEndian::HostSwap16(aServer16); }
1402
1403 /**
1404 * Gets the Server Data.
1405 *
1406 * @param[out] aServerData A reference to a`ServerData` to return the data.
1407 */
GetServerData(ServerData & aServerData) const1408 void GetServerData(ServerData &aServerData) const { aServerData.Init(GetServerData(), GetServerDataLength()); }
1409
1410 /**
1411 * Gets the Server Data bytes.
1412 *
1413 * @returns A pointer to start of the Server Data bytes.
1414 */
GetServerData(void) const1415 const uint8_t *GetServerData(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
1416
1417 /**
1418 * Returns the Server Data length in bytes.
1419 *
1420 * @returns The Server Data length in bytes.
1421 */
GetServerDataLength(void) const1422 uint8_t GetServerDataLength(void) const { return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv)); }
1423
1424 /**
1425 * Indicates whether two Server TLVs fully match.
1426 *
1427 * @param[in] aOther Another Server TLV to compare with it.
1428 *
1429 * @retval TRUE The two TLVs are equal.
1430 * @retval FALSE The two TLVs are not equal.
1431 */
operator ==(const ServerTlv & aOther) const1432 bool operator==(const ServerTlv &aOther) const
1433 {
1434 return (GetLength() == aOther.GetLength()) && (memcmp(GetValue(), aOther.GetValue(), GetLength()) == 0);
1435 }
1436
1437 /**
1438 * Calculates the total size (number of bytes) of a Service TLV with a given Server Data length.
1439 *
1440 * Note that the returned size does include the Type and Length fields in the TLV.
1441 *
1442 * @param[in] aServerDataLength Server Data length in bytes.
1443 *
1444 * @returns The size (number of bytes) of the Server TLV.
1445 */
CalculateSize(uint8_t aServerDataLength)1446 static uint16_t CalculateSize(uint8_t aServerDataLength) { return sizeof(ServerTlv) + aServerDataLength; }
1447
1448 private:
GetServerData(void)1449 uint8_t *GetServerData(void) { return AsNonConst(AsConst(this)->GetServerData()); }
1450
1451 uint16_t mServer16;
1452 } OT_TOOL_PACKED_END;
1453
1454 /**
1455 * Represents a Network Data TLV iterator.
1456 */
1457 class TlvIterator
1458 {
1459 public:
1460 /**
1461 * Initializes the `TlvIterator` to iterate over a given sequence of TLVs.
1462 *
1463 * @param[in] aStart A pointer to the start of the TLV sequence.
1464 * @param[in] aEnd A pointer to the end of the TLV sequence.
1465 */
TlvIterator(const NetworkDataTlv * aStart,const NetworkDataTlv * aEnd)1466 TlvIterator(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
1467 : mStart(aStart)
1468 , mEnd(aEnd)
1469 {
1470 }
1471
1472 /**
1473 * Initializes the `TlvIterator` to iterate over TLVs from a given buffer.
1474 *
1475 * @param[in] aBuffer A pointer to a buffer containing the TLVs.
1476 * @param[in] aLength The length (number of bytes) of @p aBuffer.
1477 */
TlvIterator(const uint8_t * aBuffer,uint8_t aLength)1478 TlvIterator(const uint8_t *aBuffer, uint8_t aLength)
1479 : TlvIterator(reinterpret_cast<const NetworkDataTlv *>(aBuffer),
1480 reinterpret_cast<const NetworkDataTlv *>(aBuffer + aLength))
1481 {
1482 }
1483
1484 /**
1485 * Initializes the `TlvIterator` to iterate over sub-TLVs of a given Prefix TLV.
1486 *
1487 * @param[in] aPrefixTlv A Prefix TLV to iterate over its sub-TLVs.
1488 */
TlvIterator(const PrefixTlv & aPrefixTlv)1489 explicit TlvIterator(const PrefixTlv &aPrefixTlv)
1490 : TlvIterator(aPrefixTlv.GetSubTlvs(), aPrefixTlv.GetNext())
1491 {
1492 }
1493
1494 /**
1495 * Initializes the `TlvIterator` to iterate over sub-TLVs of a given Service TLV.
1496 *
1497 * @param[in] aServiceTlv A Service TLV to iterate over its sub-TLVs.
1498 */
TlvIterator(const ServiceTlv & aServiceTlv)1499 explicit TlvIterator(const ServiceTlv &aServiceTlv)
1500 : TlvIterator(aServiceTlv.GetSubTlvs(), aServiceTlv.GetNext())
1501 {
1502 }
1503
1504 /**
1505 * Iterates to the next TLV with a given type.
1506 *
1507 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
1508 *
1509 * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
1510 */
Iterate(void)1511 template <typename TlvType> const TlvType *Iterate(void) { return As<TlvType>(Iterate(TlvType::kType)); }
1512
1513 /**
1514 * Iterates to the next TLV with a given type and stable flag.
1515 *
1516 * @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
1517 *
1518 * @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
1519 *
1520 * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
1521 */
Iterate(bool aStable)1522 template <typename TlvType> const TlvType *Iterate(bool aStable)
1523 {
1524 return As<TlvType>(Iterate(TlvType::kType, aStable));
1525 }
1526
1527 private:
1528 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType);
1529 const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType, bool aStable);
1530
1531 const NetworkDataTlv *mStart;
1532 const NetworkDataTlv *mEnd;
1533 };
1534
1535 /**
1536 * @}
1537 */
1538
1539 } // namespace NetworkData
1540 } // namespace ot
1541
1542 #endif // NETWORK_DATA_TLVS_HPP_
1543