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 MeshCoP TLVs.
32  *
33  */
34 
35 #ifndef MESHCOP_TLVS_HPP_
36 #define MESHCOP_TLVS_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include <openthread/commissioner.h>
41 #include <openthread/dataset.h>
42 #include <openthread/platform/radio.h>
43 
44 #include "common/const_cast.hpp"
45 #include "common/encoding.hpp"
46 #include "common/message.hpp"
47 #include "common/num_utils.hpp"
48 #include "common/string.hpp"
49 #include "common/tlvs.hpp"
50 #include "mac/mac_types.hpp"
51 #include "meshcop/extended_panid.hpp"
52 #include "meshcop/network_name.hpp"
53 #include "meshcop/timestamp.hpp"
54 #include "net/ip6_address.hpp"
55 #include "radio/radio.hpp"
56 #include "thread/key_manager.hpp"
57 #include "thread/mle_tlvs.hpp"
58 #include "thread/mle_types.hpp"
59 
60 namespace ot {
61 namespace MeshCoP {
62 
63 /**
64  * Implements MeshCoP TLV generation and parsing.
65  *
66  */
67 OT_TOOL_PACKED_BEGIN
68 class Tlv : public ot::Tlv
69 {
70 public:
71     /**
72      * MeshCoP TLV Types.
73      *
74      */
75     enum Type : uint8_t
76     {
77         kChannel                 = OT_MESHCOP_TLV_CHANNEL,                  ///< Channel TLV
78         kPanId                   = OT_MESHCOP_TLV_PANID,                    ///< PAN ID TLV
79         kExtendedPanId           = OT_MESHCOP_TLV_EXTPANID,                 ///< Extended PAN ID TLV
80         kNetworkName             = OT_MESHCOP_TLV_NETWORKNAME,              ///< Network Name TLV
81         kPskc                    = OT_MESHCOP_TLV_PSKC,                     ///< PSKc TLV
82         kNetworkKey              = OT_MESHCOP_TLV_NETWORKKEY,               ///< Network Network Key TLV
83         kNetworkKeySequence      = OT_MESHCOP_TLV_NETWORK_KEY_SEQUENCE,     ///< Network Key Sequence TLV
84         kMeshLocalPrefix         = OT_MESHCOP_TLV_MESHLOCALPREFIX,          ///< Mesh Local Prefix TLV
85         kSteeringData            = OT_MESHCOP_TLV_STEERING_DATA,            ///< Steering Data TLV
86         kBorderAgentLocator      = OT_MESHCOP_TLV_BORDER_AGENT_RLOC,        ///< Border Agent Locator TLV
87         kCommissionerId          = OT_MESHCOP_TLV_COMMISSIONER_ID,          ///< Commissioner ID TLV
88         kCommissionerSessionId   = OT_MESHCOP_TLV_COMM_SESSION_ID,          ///< Commissioner Session ID TLV
89         kSecurityPolicy          = OT_MESHCOP_TLV_SECURITYPOLICY,           ///< Security Policy TLV
90         kGet                     = OT_MESHCOP_TLV_GET,                      ///< Get TLV
91         kActiveTimestamp         = OT_MESHCOP_TLV_ACTIVETIMESTAMP,          ///< Active Timestamp TLV
92         kCommissionerUdpPort     = OT_MESHCOP_TLV_COMMISSIONER_UDP_PORT,    ///< Commissioner UDP Port TLV
93         kState                   = OT_MESHCOP_TLV_STATE,                    ///< State TLV
94         kJoinerDtlsEncapsulation = OT_MESHCOP_TLV_JOINER_DTLS,              ///< Joiner DTLS Encapsulation TLV
95         kJoinerUdpPort           = OT_MESHCOP_TLV_JOINER_UDP_PORT,          ///< Joiner UDP Port TLV
96         kJoinerIid               = OT_MESHCOP_TLV_JOINER_IID,               ///< Joiner IID TLV
97         kJoinerRouterLocator     = OT_MESHCOP_TLV_JOINER_RLOC,              ///< Joiner Router Locator TLV
98         kJoinerRouterKek         = OT_MESHCOP_TLV_JOINER_ROUTER_KEK,        ///< Joiner Router KEK TLV
99         kProvisioningUrl         = OT_MESHCOP_TLV_PROVISIONING_URL,         ///< Provisioning URL TLV
100         kVendorName              = OT_MESHCOP_TLV_VENDOR_NAME_TLV,          ///< meshcop Vendor Name TLV
101         kVendorModel             = OT_MESHCOP_TLV_VENDOR_MODEL_TLV,         ///< meshcop Vendor Model TLV
102         kVendorSwVersion         = OT_MESHCOP_TLV_VENDOR_SW_VERSION_TLV,    ///< meshcop Vendor SW Version TLV
103         kVendorData              = OT_MESHCOP_TLV_VENDOR_DATA_TLV,          ///< meshcop Vendor Data TLV
104         kVendorStackVersion      = OT_MESHCOP_TLV_VENDOR_STACK_VERSION_TLV, ///< meshcop Vendor Stack Version TLV
105         kUdpEncapsulation        = OT_MESHCOP_TLV_UDP_ENCAPSULATION_TLV,    ///< meshcop UDP encapsulation TLV
106         kIp6Address              = OT_MESHCOP_TLV_IPV6_ADDRESS_TLV,         ///< meshcop IPv6 address TLV
107         kPendingTimestamp        = OT_MESHCOP_TLV_PENDINGTIMESTAMP,         ///< Pending Timestamp TLV
108         kDelayTimer              = OT_MESHCOP_TLV_DELAYTIMER,               ///< Delay Timer TLV
109         kChannelMask             = OT_MESHCOP_TLV_CHANNELMASK,              ///< Channel Mask TLV
110         kCount                   = OT_MESHCOP_TLV_COUNT,                    ///< Count TLV
111         kPeriod                  = OT_MESHCOP_TLV_PERIOD,                   ///< Period TLV
112         kScanDuration            = OT_MESHCOP_TLV_SCAN_DURATION,            ///< Scan Duration TLV
113         kEnergyList              = OT_MESHCOP_TLV_ENERGY_LIST,              ///< Energy List TLV
114         kDiscoveryRequest        = OT_MESHCOP_TLV_DISCOVERYREQUEST,         ///< Discovery Request TLV
115         kDiscoveryResponse       = OT_MESHCOP_TLV_DISCOVERYRESPONSE,        ///< Discovery Response TLV
116         kJoinerAdvertisement     = OT_MESHCOP_TLV_JOINERADVERTISEMENT,      ///< Joiner Advertisement TLV
117     };
118 
119     /**
120      * Max length of Provisioning URL TLV.
121      *
122      */
123     static constexpr uint8_t kMaxProvisioningUrlLength = OT_PROVISIONING_URL_MAX_SIZE;
124 
125     static constexpr uint8_t kMaxCommissionerIdLength  = 64; ///< Max length of Commissioner ID TLV.
126     static constexpr uint8_t kMaxVendorNameLength      = 32; ///< Max length of Vendor Name TLV.
127     static constexpr uint8_t kMaxVendorModelLength     = 32; ///< Max length of Vendor Model TLV.
128     static constexpr uint8_t kMaxVendorSwVersionLength = 16; ///< Max length of Vendor SW Version TLV.
129     static constexpr uint8_t kMaxVendorDataLength      = 64; ///< Max length of Vendor Data TLV.
130 
131     /**
132      * Returns the Type value.
133      *
134      * @returns The Type value.
135      *
136      */
GetType(void) const137     Type GetType(void) const { return static_cast<Type>(ot::Tlv::GetType()); }
138 
139     /**
140      * Sets the Type value.
141      *
142      * @param[in]  aType  The Type value.
143      *
144      */
SetType(Type aType)145     void SetType(Type aType) { ot::Tlv::SetType(static_cast<uint8_t>(aType)); }
146 
147     /**
148      * Returns a pointer to the next TLV.
149      *
150      * @returns A pointer to the next TLV.
151      *
152      */
GetNext(void)153     Tlv *GetNext(void) { return As<Tlv>(ot::Tlv::GetNext()); }
154 
155     /**
156      * Returns a pointer to the next TLV.
157      *
158      * @returns A pointer to the next TLV.
159      *
160      */
GetNext(void) const161     const Tlv *GetNext(void) const { return As<Tlv>(ot::Tlv::GetNext()); }
162 
163     /**
164      * Indicates whether a TLV appears to be well-formed.
165      *
166      * @param[in]  aTlv  A reference to the TLV.
167      *
168      * @returns TRUE if the TLV appears to be well-formed, FALSE otherwise.
169      *
170      */
171     static bool IsValid(const Tlv &aTlv);
172 
173 } OT_TOOL_PACKED_END;
174 
175 /**
176  * Implements extended MeshCoP TLV generation and parsing.
177  *
178  */
179 OT_TOOL_PACKED_BEGIN
180 class ExtendedTlv : public ot::ExtendedTlv
181 {
182 public:
183     /**
184      * Returns the Type value.
185      *
186      * @returns The Type value.
187      *
188      */
GetType(void) const189     MeshCoP::Tlv::Type GetType(void) const { return static_cast<MeshCoP::Tlv::Type>(ot::ExtendedTlv::GetType()); }
190 
191     /**
192      * Sets the Type value.
193      *
194      * @param[in]  aType  The Type value.
195      *
196      */
SetType(MeshCoP::Tlv::Type aType)197     void SetType(MeshCoP::Tlv::Type aType) { ot::ExtendedTlv::SetType(static_cast<uint8_t>(aType)); }
198 } OT_TOOL_PACKED_END;
199 
200 /**
201  * Defines Commissioner UDP Port TLV constants and types.
202  *
203  */
204 typedef UintTlvInfo<Tlv::kCommissionerUdpPort, uint16_t> CommissionerUdpPortTlv;
205 
206 /**
207  * Defines IPv6 Address TLV constants and types.
208  *
209  */
210 typedef SimpleTlvInfo<Tlv::kIp6Address, Ip6::Address> Ip6AddressTlv;
211 
212 /**
213  * Defines Joiner IID TLV constants and types.
214  *
215  */
216 typedef SimpleTlvInfo<Tlv::kJoinerIid, Ip6::InterfaceIdentifier> JoinerIidTlv;
217 
218 /**
219  * Defines Joiner Router Locator TLV constants and types.
220  *
221  */
222 typedef UintTlvInfo<Tlv::kJoinerRouterLocator, uint16_t> JoinerRouterLocatorTlv;
223 
224 /**
225  * Defines Joiner Router KEK TLV constants and types.
226  *
227  */
228 typedef SimpleTlvInfo<Tlv::kJoinerRouterKek, Kek> JoinerRouterKekTlv;
229 
230 /**
231  * Defines Count TLV constants and types.
232  *
233  */
234 typedef UintTlvInfo<Tlv::kCount, uint8_t> CountTlv;
235 
236 /**
237  * Defines Period TLV constants and types.
238  *
239  */
240 typedef UintTlvInfo<Tlv::kPeriod, uint16_t> PeriodTlv;
241 
242 /**
243  * Defines Scan Duration TLV constants and types.
244  *
245  */
246 typedef UintTlvInfo<Tlv::kScanDuration, uint16_t> ScanDurationTlv;
247 
248 /**
249  * Defines Commissioner ID TLV constants and types.
250  *
251  */
252 typedef StringTlvInfo<Tlv::kCommissionerId, Tlv::kMaxCommissionerIdLength> CommissionerIdTlv;
253 
254 /**
255  * Implements Channel TLV value format.
256  *
257  */
258 typedef Mle::ChannelTlvValue ChannelTlvValue;
259 
260 /**
261  * Defines Channel TLV constants and types.
262  *
263  */
264 typedef SimpleTlvInfo<Tlv::kChannel, ChannelTlvValue> ChannelTlv;
265 
266 /**
267  * Defines PAN ID TLV constants and types.
268  *
269  */
270 typedef UintTlvInfo<Tlv::kPanId, uint16_t> PanIdTlv;
271 
272 /**
273  * Defines Extended PAN ID TLV constants and types.
274  *
275  */
276 typedef SimpleTlvInfo<Tlv::kExtendedPanId, ExtendedPanId> ExtendedPanIdTlv;
277 
278 /**
279  * Implements Network Name TLV generation and parsing.
280  *
281  */
282 OT_TOOL_PACKED_BEGIN
283 class NetworkNameTlv : public Tlv, public TlvInfo<Tlv::kNetworkName>
284 {
285 public:
286     /**
287      * Initializes the TLV.
288      *
289      */
Init(void)290     void Init(void)
291     {
292         SetType(kNetworkName);
293         SetLength(sizeof(*this) - sizeof(Tlv));
294     }
295 
296     /**
297      * Indicates whether or not the TLV appears to be well-formed.
298      *
299      * @retval TRUE   If the TLV appears to be well-formed.
300      * @retval FALSE  If the TLV does not appear to be well-formed.
301      *
302      */
303     bool IsValid(void) const;
304 
305     /**
306      * Gets the Network Name value.
307      *
308      * @returns The Network Name value (as `NameData`).
309      *
310      */
311     NameData GetNetworkName(void) const;
312 
313     /**
314      * Sets the Network Name value.
315      *
316      * @param[in] aNameData   A Network Name value (as `NameData`).
317      *
318      */
319     void SetNetworkName(const NameData &aNameData);
320 
321 private:
322     char mNetworkName[NetworkName::kMaxSize];
323 } OT_TOOL_PACKED_END;
324 
325 /**
326  * Defines PSKc TLV constants and types.
327  *
328  */
329 typedef SimpleTlvInfo<Tlv::kPskc, Pskc> PskcTlv;
330 
331 /**
332  * Defines Network Key TLV constants and types.
333  *
334  */
335 typedef SimpleTlvInfo<Tlv::kNetworkKey, NetworkKey> NetworkKeyTlv;
336 
337 /**
338  * Defines Network Key Sequence TLV constants and types.
339  *
340  */
341 typedef UintTlvInfo<Tlv::kNetworkKeySequence, uint32_t> NetworkKeySequenceTlv;
342 
343 /**
344  * Defines Mesh Local Prefix TLV constants and types.
345  *
346  */
347 typedef SimpleTlvInfo<Tlv::kMeshLocalPrefix, Ip6::NetworkPrefix> MeshLocalPrefixTlv;
348 
349 class SteeringData;
350 
351 /**
352  * Implements Steering Data TLV generation and parsing.
353  *
354  */
355 OT_TOOL_PACKED_BEGIN
356 class SteeringDataTlv : public Tlv, public TlvInfo<Tlv::kSteeringData>
357 {
358 public:
359     /**
360      * Initializes the TLV.
361      *
362      */
Init(void)363     void Init(void)
364     {
365         SetType(kSteeringData);
366         SetLength(sizeof(*this) - sizeof(Tlv));
367         Clear();
368     }
369 
370     /**
371      * Indicates whether or not the TLV appears to be well-formed.
372      *
373      * @retval TRUE   If the TLV appears to be well-formed.
374      * @retval FALSE  If the TLV does not appear to be well-formed.
375      *
376      */
IsValid(void) const377     bool IsValid(void) const { return GetLength() > 0; }
378 
379     /**
380      * Returns the Steering Data length.
381      *
382      * @returns The Steering Data length.
383      *
384      */
GetSteeringDataLength(void) const385     uint8_t GetSteeringDataLength(void) const
386     {
387         return GetLength() <= sizeof(mSteeringData) ? GetLength() : sizeof(mSteeringData);
388     }
389 
390     /**
391      * Sets all bits in the Bloom Filter to zero.
392      *
393      */
Clear(void)394     void Clear(void) { memset(mSteeringData, 0, GetSteeringDataLength()); }
395 
396     /**
397      * Copies the Steering Data from the TLV into a given `SteeringData` variable.
398      *
399      * @param[out]  aSteeringData   A reference to a `SteeringData` to copy into.
400      *
401      */
402     void CopyTo(SteeringData &aSteeringData) const;
403 
404 private:
405     uint8_t mSteeringData[OT_STEERING_DATA_MAX_LENGTH];
406 } OT_TOOL_PACKED_END;
407 
408 /**
409  * Implements Border Agent Locator TLV generation and parsing.
410  *
411  */
412 OT_TOOL_PACKED_BEGIN
413 class BorderAgentLocatorTlv : public Tlv, public UintTlvInfo<Tlv::kBorderAgentLocator, uint16_t>
414 {
415 public:
416     /**
417      * Initializes the TLV.
418      *
419      */
Init(void)420     void Init(void)
421     {
422         SetType(kBorderAgentLocator);
423         SetLength(sizeof(*this) - sizeof(Tlv));
424     }
425 
426     /**
427      * Indicates whether or not the TLV appears to be well-formed.
428      *
429      * @retval TRUE   If the TLV appears to be well-formed.
430      * @retval FALSE  If the TLV does not appear to be well-formed.
431      *
432      */
IsValid(void) const433     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
434 
435     /**
436      * Returns the Border Agent Locator value.
437      *
438      * @returns The Border Agent Locator value.
439      *
440      */
GetBorderAgentLocator(void) const441     uint16_t GetBorderAgentLocator(void) const { return BigEndian::HostSwap16(mLocator); }
442 
443     /**
444      * Sets the Border Agent Locator value.
445      *
446      * @param[in]  aLocator  The Border Agent Locator value.
447      *
448      */
SetBorderAgentLocator(uint16_t aLocator)449     void SetBorderAgentLocator(uint16_t aLocator) { mLocator = BigEndian::HostSwap16(aLocator); }
450 
451 private:
452     uint16_t mLocator;
453 } OT_TOOL_PACKED_END;
454 
455 /**
456  * Implements Commissioner Session ID TLV generation and parsing.
457  *
458  */
459 OT_TOOL_PACKED_BEGIN
460 class CommissionerSessionIdTlv : public Tlv, public UintTlvInfo<Tlv::kCommissionerSessionId, uint16_t>
461 {
462 public:
463     /**
464      * Initializes the TLV.
465      *
466      */
Init(void)467     void Init(void)
468     {
469         SetType(kCommissionerSessionId);
470         SetLength(sizeof(*this) - sizeof(Tlv));
471     }
472 
473     /**
474      * Indicates whether or not the TLV appears to be well-formed.
475      *
476      * @retval TRUE   If the TLV appears to be well-formed.
477      * @retval FALSE  If the TLV does not appear to be well-formed.
478      *
479      */
IsValid(void) const480     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
481 
482     /**
483      * Returns the Commissioner Session ID value.
484      *
485      * @returns The Commissioner Session ID value.
486      *
487      */
GetCommissionerSessionId(void) const488     uint16_t GetCommissionerSessionId(void) const { return BigEndian::HostSwap16(mSessionId); }
489 
490     /**
491      * Sets the Commissioner Session ID value.
492      *
493      * @param[in]  aSessionId  The Commissioner Session ID value.
494      *
495      */
SetCommissionerSessionId(uint16_t aSessionId)496     void SetCommissionerSessionId(uint16_t aSessionId) { mSessionId = BigEndian::HostSwap16(aSessionId); }
497 
498 private:
499     uint16_t mSessionId;
500 } OT_TOOL_PACKED_END;
501 
502 /**
503  * Implements Security Policy TLV generation and parsing.
504  *
505  */
506 OT_TOOL_PACKED_BEGIN
507 class SecurityPolicyTlv : public Tlv, public TlvInfo<Tlv::kSecurityPolicy>
508 {
509 public:
510     /**
511      * Initializes the TLV.
512      *
513      */
Init(void)514     void Init(void)
515     {
516         SetType(kSecurityPolicy);
517         SetLength(sizeof(*this) - sizeof(Tlv));
518     }
519 
520     /**
521      * Indicates whether or not the TLV appears to be well-formed.
522      *
523      * @retval TRUE   If the TLV appears to be well-formed.
524      * @retval FALSE  If the TLV does not appear to be well-formed.
525      *
526      */
527     bool IsValid(void) const;
528 
529     /**
530      * Returns the Security Policy.
531      *
532      * @returns  The Security Policy.
533      *
534      */
535     SecurityPolicy GetSecurityPolicy(void) const;
536 
537     /**
538      * Sets the Security Policy.
539      *
540      * @param[in]  aSecurityPolicy  The Security Policy which will be set.
541      *
542      */
543     void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy);
544 
545 private:
546     static constexpr uint8_t kThread11FlagsLength = 1; // The Thread 1.1 Security Policy Flags length.
547     static constexpr uint8_t kThread12FlagsLength = 2; // The Thread 1.2 Security Policy Flags length.
548 
SetRotationTime(uint16_t aRotationTime)549     void     SetRotationTime(uint16_t aRotationTime) { mRotationTime = BigEndian::HostSwap16(aRotationTime); }
GetRotationTime(void) const550     uint16_t GetRotationTime(void) const { return BigEndian::HostSwap16(mRotationTime); }
GetFlagsLength(void) const551     uint8_t  GetFlagsLength(void) const { return GetLength() - sizeof(mRotationTime); }
552 
553     uint16_t mRotationTime;
554 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
555     uint8_t mFlags[kThread12FlagsLength];
556 #else
557     uint8_t mFlags[kThread11FlagsLength];
558 #endif
559 } OT_TOOL_PACKED_END;
560 
561 /**
562  * Defines Active Timestamp TLV constants and types.
563  *
564  */
565 typedef SimpleTlvInfo<Tlv::kActiveTimestamp, Timestamp> ActiveTimestampTlv;
566 
567 /**
568  * Implements State TLV generation and parsing.
569  *
570  */
571 class StateTlv : public UintTlvInfo<Tlv::kState, uint8_t>
572 {
573 public:
574     StateTlv(void) = delete;
575 
576     /**
577      * State values.
578      *
579      */
580     enum State : uint8_t
581     {
582         kReject  = 0xff, ///< Reject (-1)
583         kPending = 0,    ///< Pending
584         kAccept  = 1,    ///< Accept
585     };
586 
587     /**
588      * Converts a `State` to a string.
589      *
590      * @param[in] aState  An item state.
591      *
592      * @returns A string representation of @p aState.
593      *
594      */
595     static const char *StateToString(State aState);
596 };
597 
598 /**
599  * Defines Joiner UDP Port TLV constants and types.
600  *
601  */
602 typedef UintTlvInfo<Tlv::kJoinerUdpPort, uint16_t> JoinerUdpPortTlv;
603 
604 /**
605  * Defines Pending Timestamp TLV constants and types.
606  *
607  */
608 typedef SimpleTlvInfo<Tlv::kPendingTimestamp, Timestamp> PendingTimestampTlv;
609 
610 /**
611  * Defines Delay Timer TLV constants and types.
612  *
613  */
614 typedef UintTlvInfo<Tlv::kDelayTimer, uint32_t> DelayTimerTlv;
615 
616 /**
617  * Implements Channel Mask TLV generation and parsing.
618  *
619  */
620 OT_TOOL_PACKED_BEGIN
621 class ChannelMaskTlv : public Tlv, public TlvInfo<Tlv::kChannelMask>
622 {
623     static constexpr uint8_t kEntryHeaderSize = 2; // Two bytes: mChannelPage and mMaskLength
624     static constexpr uint8_t kEntrySize       = kEntryHeaderSize + sizeof(uint32_t);
625 
626 public:
627     /**
628      * Represents Channel Mask TLV value to append.
629      *
630      */
631     struct Value
632     {
633         static constexpr uint16_t kMaxLength = (kEntrySize * Radio::kNumChannelPages); ///< Max value length.
634 
635         uint8_t mData[kMaxLength]; ///< Array to store TLV value (encoded as one or more Channel Mask TLV Entry)
636         uint8_t mLength;           ///< Value length in bytes.
637     };
638 
639     ChannelMaskTlv(void) = delete;
640 
641     /**
642      * Parses the Channel Mask TLV value and validates that all the included entries are well-formed.
643      *
644      * @returns TRUE if the TLV is well-formed, FALSE otherwise.
645      *
646      */
647     bool IsValid(void) const;
648 
649     /**
650      * Parses and retrieves the combined channel mask for all supported channel pages from entries in the TLV.
651      *
652      * @param[out] aChannelMask  A reference to return the channel mask.
653      *
654      * @retval kErrorNone   Successfully parsed the TLV value, @p aChannelMask is updated.
655      * @retval kErrorParse  TLV value is not well-formed.
656      *
657      */
658     Error ReadChannelMask(uint32_t &aChannelMask) const;
659 
660     /**
661      * Searches within a given message for Channel Mask TLV, parses and validates the TLV value and returns the
662      * combined channel mask for all supported channel pages included in the TLV.
663      *
664      * @param[in]  aMessage      The message to search in.
665      * @param[out] aChannelMask  A reference to return the channel mask.
666      *
667      * @retval kErrorNone       Found the TLV, successfully parsed its value, @p aChannelMask is updated.
668      * @retval kErrorNotFound   No Channel Mask TLV found in the @p aMessage.
669      * @retval kErrorParse      Found the TLV, but failed to parse it.
670      *
671      */
672     static Error FindIn(const Message &aMessage, uint32_t &aChannelMask);
673 
674     /**
675      * Prepares Channel Mask TLV value for appending/writing.
676      *
677      * @param[out] aValue        A reference to `Value` structure to populate.
678      * @param[in]  aChannelMask  The combined channel mask for all supported channel pages.
679      *
680      */
681     static void PrepareValue(Value &aValue, uint32_t aChannelMask);
682 
683     /**
684      * Prepares a Channel Mask TLV value and appends the TLV to a given message.
685      *
686      * @param[in] aMessage       The message to append to.
687      * @param[in] aChannelMask   The combined channel mask for all supported channel pages.
688      *
689      * @retval kErrorNone    Successfully prepared the Channel Mask TLV and appended it to @p aMessage.
690      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
691      *
692      */
693     static Error AppendTo(Message &aMessage, uint32_t aChannelMask);
694 
695 private:
696     static constexpr uint8_t kMaskLength = sizeof(uint32_t);
697 
698     OT_TOOL_PACKED_BEGIN
699     class Entry
700     {
701     public:
GetChannelPage(void) const702         uint8_t  GetChannelPage(void) const { return mChannelPage; }
SetChannelPage(uint8_t aChannelPage)703         void     SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; }
GetMaskLength(void) const704         uint8_t  GetMaskLength(void) const { return mMaskLength; }
SetMaskLength(uint8_t aMaskLength)705         void     SetMaskLength(uint8_t aMaskLength) { mMaskLength = aMaskLength; }
GetMask(void) const706         uint32_t GetMask(void) const { return Reverse32(BigEndian::HostSwap32(mMask)); }
SetMask(uint32_t aMask)707         void     SetMask(uint32_t aMask) { mMask = BigEndian::HostSwap32(Reverse32(aMask)); }
708 
709     private:
710         uint8_t  mChannelPage;
711         uint8_t  mMaskLength;
712         uint32_t mMask;
713     } OT_TOOL_PACKED_END;
714 
715     struct EntriesData : public Clearable<EntriesData>
716     {
717         // Represents received Channel Mask TLV Entries data which
718         // is either contained in `mData` buffer, or in `mMessage`
719         // at `mOffset`.
720 
721         Error Parse(uint32_t &aChannelMask);
722 
723         const uint8_t *mData;
724         const Message *mMessage;
725         uint16_t       mOffset;
726         uint16_t       mLength;
727     };
728 
729     uint8_t mEntriesStart;
730 } OT_TOOL_PACKED_BEGIN;
731 
732 /**
733  * Implements Energy List TLV generation and parsing.
734  *
735  */
736 OT_TOOL_PACKED_BEGIN
737 class EnergyListTlv : public Tlv, public TlvInfo<Tlv::kEnergyList>
738 {
739 public:
740     /**
741      * Initializes the TLV.
742      *
743      */
Init(void)744     void Init(void)
745     {
746         SetType(kEnergyList);
747         SetLength(sizeof(*this) - sizeof(Tlv));
748     }
749 
750     /**
751      * Indicates whether or not the TLV appears to be well-formed.
752      *
753      * @retval TRUE   If the TLV appears to be well-formed.
754      * @retval FALSE  If the TLV does not appear to be well-formed.
755      *
756      */
IsValid(void) const757     bool IsValid(void) const { return true; }
758 
759     /**
760      * Returns a pointer to the start of energy measurement list.
761      *
762      * @returns A pointer to the start start of energy energy measurement list.
763      *
764      */
GetEnergyList(void) const765     const uint8_t *GetEnergyList(void) const { return mEnergyList; }
766 
767     /**
768      * Returns the length of energy measurement list.
769      *
770      * @returns The length of energy measurement list.
771      *
772      */
GetEnergyListLength(void) const773     uint8_t GetEnergyListLength(void) const { return Min(kMaxListLength, GetLength()); }
774 
775 private:
776     static constexpr uint8_t kMaxListLength = OPENTHREAD_CONFIG_TMF_ENERGY_SCAN_MAX_RESULTS;
777 
778     uint8_t mEnergyList[kMaxListLength];
779 } OT_TOOL_PACKED_END;
780 
781 /**
782  * Defines Provisioning TLV constants and types.
783  *
784  */
785 typedef StringTlvInfo<Tlv::kProvisioningUrl, Tlv::kMaxProvisioningUrlLength> ProvisioningUrlTlv;
786 
787 /**
788  * Defines Vendor Name TLV constants and types.
789  *
790  */
791 typedef StringTlvInfo<Tlv::kVendorName, Tlv::kMaxVendorNameLength> VendorNameTlv;
792 
793 /**
794  * Defines Vendor Model TLV constants and types.
795  *
796  */
797 typedef StringTlvInfo<Tlv::kVendorModel, Tlv::kMaxVendorModelLength> VendorModelTlv;
798 
799 /**
800  * Defines Vendor SW Version TLV constants and types.
801  *
802  */
803 typedef StringTlvInfo<Tlv::kVendorSwVersion, Tlv::kMaxVendorSwVersionLength> VendorSwVersionTlv;
804 
805 /**
806  * Defines Vendor Data TLV constants and types.
807  *
808  */
809 typedef StringTlvInfo<Tlv::kVendorData, Tlv::kMaxVendorDataLength> VendorDataTlv;
810 
811 /**
812  * Implements Vendor Stack Version TLV generation and parsing.
813  *
814  */
815 OT_TOOL_PACKED_BEGIN
816 class VendorStackVersionTlv : public Tlv, public TlvInfo<Tlv::kVendorStackVersion>
817 {
818 public:
819     /**
820      * Default constructor.
821      *
822      */
VendorStackVersionTlv(void)823     VendorStackVersionTlv(void)
824         : mBuildRevision(0)
825         , mMinorMajor(0)
826     {
827     }
828 
829     /**
830      * Initializes the TLV.
831      *
832      */
Init(void)833     void Init(void)
834     {
835         SetType(kVendorStackVersion);
836         SetLength(sizeof(*this) - sizeof(Tlv));
837     }
838 
839     /**
840      * Indicates whether or not the TLV appears to be well-formed.
841      *
842      * @retval TRUE   If the TLV appears to be well-formed.
843      * @retval FALSE  If the TLV does not appear to be well-formed.
844      *
845      */
IsValid(void) const846     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
847 
848     /**
849      * Returns the Stack Vendor OUI value.
850      *
851      * @returns The Vendor Stack Vendor OUI value.
852      *
853      */
GetOui(void) const854     uint32_t GetOui(void) const { return BigEndian::ReadUint24(mOui); }
855 
856     /**
857      * Returns the Stack Vendor OUI value.
858      *
859      * @param[in]  aOui  The Vendor Stack Vendor OUI value.
860      *
861      */
SetOui(uint32_t aOui)862     void SetOui(uint32_t aOui) { BigEndian::WriteUint24(aOui, mOui); }
863 
864     /**
865      * Returns the Build value.
866      *
867      * @returns The Build value.
868      *
869      */
GetBuild(void) const870     uint16_t GetBuild(void) const { return (BigEndian::HostSwap16(mBuildRevision) & kBuildMask) >> kBuildOffset; }
871 
872     /**
873      * Sets the Build value.
874      *
875      * @param[in]  aBuild  The Build value.
876      *
877      */
SetBuild(uint16_t aBuild)878     void SetBuild(uint16_t aBuild)
879     {
880         mBuildRevision = BigEndian::HostSwap16((BigEndian::HostSwap16(mBuildRevision) & ~kBuildMask) |
881                                                ((aBuild << kBuildOffset) & kBuildMask));
882     }
883 
884     /**
885      * Returns the Revision value.
886      *
887      * @returns The Revision value.
888      *
889      */
GetRevision(void) const890     uint8_t GetRevision(void) const { return (BigEndian::HostSwap16(mBuildRevision) & kRevMask) >> kRevOffset; }
891 
892     /**
893      * Sets the Revision value.
894      *
895      * @param[in]  aRevision  The Revision value.
896      *
897      */
SetRevision(uint8_t aRevision)898     void SetRevision(uint8_t aRevision)
899     {
900         mBuildRevision = BigEndian::HostSwap16((BigEndian::HostSwap16(mBuildRevision) & ~kRevMask) |
901                                                ((aRevision << kRevOffset) & kRevMask));
902     }
903 
904     /**
905      * Returns the Minor value.
906      *
907      * @returns The Minor value.
908      *
909      */
GetMinor(void) const910     uint8_t GetMinor(void) const { return (mMinorMajor & kMinorMask) >> kMinorOffset; }
911 
912     /**
913      * Sets the Minor value.
914      *
915      * @param[in]  aMinor  The Minor value.
916      *
917      */
SetMinor(uint8_t aMinor)918     void SetMinor(uint8_t aMinor)
919     {
920         mMinorMajor = (mMinorMajor & ~kMinorMask) | ((aMinor << kMinorOffset) & kMinorMask);
921     }
922 
923     /**
924      * Returns the Major value.
925      *
926      * @returns The Major value.
927      *
928      */
GetMajor(void) const929     uint8_t GetMajor(void) const { return (mMinorMajor & kMajorMask) >> kMajorOffset; }
930 
931     /**
932      * Sets the Major value.
933      *
934      * @param[in] aMajor  The Major value.
935      *
936      */
SetMajor(uint8_t aMajor)937     void SetMajor(uint8_t aMajor)
938     {
939         mMinorMajor = (mMinorMajor & ~kMajorMask) | ((aMajor << kMajorOffset) & kMajorMask);
940     }
941 
942 private:
943     // For `mBuildRevision`
944     static constexpr uint8_t  kBuildOffset = 4;
945     static constexpr uint16_t kBuildMask   = 0xfff << kBuildOffset;
946     static constexpr uint8_t  kRevOffset   = 0;
947     static constexpr uint16_t kRevMask     = 0xf << kBuildOffset;
948 
949     // For `mMinorMajor`
950     static constexpr uint8_t kMinorOffset = 4;
951     static constexpr uint8_t kMinorMask   = 0xf << kMinorOffset;
952     static constexpr uint8_t kMajorOffset = 0;
953     static constexpr uint8_t kMajorMask   = 0xf << kMajorOffset;
954 
955     uint8_t  mOui[3];
956     uint16_t mBuildRevision;
957     uint8_t  mMinorMajor;
958 } OT_TOOL_PACKED_END;
959 
960 /**
961  * Defines UDP Encapsulation TLV types and constants.
962  *
963  */
964 typedef TlvInfo<MeshCoP::Tlv::kUdpEncapsulation> UdpEncapsulationTlv;
965 
966 /**
967  * Represents UDP Encapsulation TLV value header (source and destination ports).
968  *
969  */
970 OT_TOOL_PACKED_BEGIN
971 class UdpEncapsulationTlvHeader
972 {
973 public:
974     /**
975      * Returns the source port.
976      *
977      * @returns The source port.
978      *
979      */
GetSourcePort(void) const980     uint16_t GetSourcePort(void) const { return BigEndian::HostSwap16(mSourcePort); }
981 
982     /**
983      * Updates the source port.
984      *
985      * @param[in]   aSourcePort     The source port.
986      *
987      */
SetSourcePort(uint16_t aSourcePort)988     void SetSourcePort(uint16_t aSourcePort) { mSourcePort = BigEndian::HostSwap16(aSourcePort); }
989 
990     /**
991      * Returns the destination port.
992      *
993      * @returns The destination port.
994      *
995      */
GetDestinationPort(void) const996     uint16_t GetDestinationPort(void) const { return BigEndian::HostSwap16(mDestinationPort); }
997 
998     /**
999      * Updates the destination port.
1000      *
1001      * @param[in]   aDestinationPort    The destination port.
1002      *
1003      */
SetDestinationPort(uint16_t aDestinationPort)1004     void SetDestinationPort(uint16_t aDestinationPort) { mDestinationPort = BigEndian::HostSwap16(aDestinationPort); }
1005 
1006 private:
1007     uint16_t mSourcePort;
1008     uint16_t mDestinationPort;
1009     // Followed by the UDP Payload.
1010 } OT_TOOL_PACKED_END;
1011 
1012 /**
1013  * Implements Discovery Request TLV generation and parsing.
1014  *
1015  */
1016 OT_TOOL_PACKED_BEGIN
1017 class DiscoveryRequestTlv : public Tlv, public TlvInfo<Tlv::kDiscoveryRequest>
1018 {
1019 public:
1020     /**
1021      * Initializes the TLV.
1022      *
1023      */
Init(void)1024     void Init(void)
1025     {
1026         SetType(kDiscoveryRequest);
1027         SetLength(sizeof(*this) - sizeof(Tlv));
1028         mFlags    = 0;
1029         mReserved = 0;
1030     }
1031 
1032     /**
1033      * Indicates whether or not the TLV appears to be well-formed.
1034      *
1035      * @retval TRUE   If the TLV appears to be well-formed.
1036      * @retval FALSE  If the TLV does not appear to be well-formed.
1037      *
1038      */
IsValid(void) const1039     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
1040 
1041     /**
1042      * Returns the Version value.
1043      *
1044      * @returns The Version value.
1045      *
1046      */
GetVersion(void) const1047     uint8_t GetVersion(void) const { return mFlags >> kVersionOffset; }
1048 
1049     /**
1050      * Sets the Version value.
1051      *
1052      * @param[in]  aVersion  The Version value.
1053      *
1054      */
SetVersion(uint8_t aVersion)1055     void SetVersion(uint8_t aVersion)
1056     {
1057         mFlags = (mFlags & ~kVersionMask) | ((aVersion << kVersionOffset) & kVersionMask);
1058     }
1059 
1060     /**
1061      * Indicates whether or not the Joiner flag is set.
1062      *
1063      * @retval TRUE   If the Joiner flag is set.
1064      * @retval FALSE  If the Joiner flag is not set.
1065      *
1066      */
IsJoiner(void) const1067     bool IsJoiner(void) const { return (mFlags & kJoinerMask) != 0; }
1068 
1069     /**
1070      * Sets the Joiner flag.
1071      *
1072      * @param[in]  aJoiner  TRUE if set, FALSE otherwise.
1073      *
1074      */
SetJoiner(bool aJoiner)1075     void SetJoiner(bool aJoiner)
1076     {
1077         if (aJoiner)
1078         {
1079             mFlags |= kJoinerMask;
1080         }
1081         else
1082         {
1083             mFlags &= ~kJoinerMask;
1084         }
1085     }
1086 
1087 private:
1088     static constexpr uint8_t kVersionOffset = 4;
1089     static constexpr uint8_t kVersionMask   = 0xf << kVersionOffset;
1090     static constexpr uint8_t kJoinerOffset  = 3;
1091     static constexpr uint8_t kJoinerMask    = 1 << kJoinerOffset;
1092 
1093     uint8_t mFlags;
1094     uint8_t mReserved;
1095 } OT_TOOL_PACKED_END;
1096 
1097 /**
1098  * Implements Discovery Response TLV generation and parsing.
1099  *
1100  */
1101 OT_TOOL_PACKED_BEGIN
1102 class DiscoveryResponseTlv : public Tlv, public TlvInfo<Tlv::kDiscoveryResponse>
1103 {
1104 public:
1105     /**
1106      * Initializes the TLV.
1107      *
1108      */
Init(void)1109     void Init(void)
1110     {
1111         SetType(kDiscoveryResponse);
1112         SetLength(sizeof(*this) - sizeof(Tlv));
1113         mFlags    = 0;
1114         mReserved = 0;
1115     }
1116 
1117     /**
1118      * Indicates whether or not the TLV appears to be well-formed.
1119      *
1120      * @retval TRUE   If the TLV appears to be well-formed.
1121      * @retval FALSE  If the TLV does not appear to be well-formed.
1122      *
1123      */
IsValid(void) const1124     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
1125 
1126     /**
1127      * Returns the Version value.
1128      *
1129      * @returns The Version value.
1130      *
1131      */
GetVersion(void) const1132     uint8_t GetVersion(void) const { return mFlags >> kVersionOffset; }
1133 
1134     /**
1135      * Sets the Version value.
1136      *
1137      * @param[in]  aVersion  The Version value.
1138      *
1139      */
SetVersion(uint8_t aVersion)1140     void SetVersion(uint8_t aVersion)
1141     {
1142         mFlags = (mFlags & ~kVersionMask) | ((aVersion << kVersionOffset) & kVersionMask);
1143     }
1144 
1145     /**
1146      * Indicates whether or not the Native Commissioner flag is set.
1147      *
1148      * @retval TRUE   If the Native Commissioner flag is set.
1149      * @retval FALSE  If the Native Commissioner flag is not set.
1150      *
1151      */
IsNativeCommissioner(void) const1152     bool IsNativeCommissioner(void) const { return (mFlags & kNativeMask) != 0; }
1153 
1154     /**
1155      * Sets the Native Commissioner flag.
1156      *
1157      * @param[in]  aNativeCommissioner  TRUE if set, FALSE otherwise.
1158      *
1159      */
SetNativeCommissioner(bool aNativeCommissioner)1160     void SetNativeCommissioner(bool aNativeCommissioner)
1161     {
1162         if (aNativeCommissioner)
1163         {
1164             mFlags |= kNativeMask;
1165         }
1166         else
1167         {
1168             mFlags &= ~kNativeMask;
1169         }
1170     }
1171 
1172     /**
1173      * Indicates whether or not the Commercial Commissioning Mode flag is set.
1174      *
1175      * @retval TRUE   If the Commercial Commissioning Mode flag is set.
1176      * @retval FALSE  If the Commercial Commissioning Mode flag is not set.
1177      *
1178      */
IsCommercialCommissioningMode(void) const1179     bool IsCommercialCommissioningMode(void) const { return (mFlags & kCcmMask) != 0; }
1180 
1181     /**
1182      * Sets the Commercial Commissioning Mode flag.
1183      *
1184      * @param[in]  aCcm  TRUE if set, FALSE otherwise.
1185      *
1186      */
SetCommercialCommissioningMode(bool aCcm)1187     void SetCommercialCommissioningMode(bool aCcm)
1188     {
1189         if (aCcm)
1190         {
1191             mFlags |= kCcmMask;
1192         }
1193         else
1194         {
1195             mFlags &= ~kCcmMask;
1196         }
1197     }
1198 
1199 private:
1200     static constexpr uint8_t kVersionOffset = 4;
1201     static constexpr uint8_t kVersionMask   = 0xf << kVersionOffset;
1202     static constexpr uint8_t kNativeOffset  = 3;
1203     static constexpr uint8_t kNativeMask    = 1 << kNativeOffset;
1204     static constexpr uint8_t kCcmOffset     = 2;
1205     static constexpr uint8_t kCcmMask       = 1 << kCcmOffset;
1206 
1207     uint8_t mFlags;
1208     uint8_t mReserved;
1209 } OT_TOOL_PACKED_END;
1210 
1211 /**
1212  * Implements Joiner Advertisement TLV generation and parsing.
1213  *
1214  */
1215 OT_TOOL_PACKED_BEGIN
1216 class JoinerAdvertisementTlv : public Tlv, public TlvInfo<Tlv::kJoinerAdvertisement>
1217 {
1218 public:
1219     static constexpr uint8_t kAdvDataMaxLength = OT_JOINER_ADVDATA_MAX_LENGTH; ///< The Max Length of AdvData
1220 
1221     /**
1222      * Initializes the TLV.
1223      *
1224      */
Init(void)1225     void Init(void)
1226     {
1227         SetType(kJoinerAdvertisement);
1228         SetLength(sizeof(*this) - sizeof(Tlv));
1229     }
1230 
1231     /**
1232      * Indicates whether or not the TLV appears to be well-formed.
1233      *
1234      * @retval TRUE   If the TLV appears to be well-formed.
1235      * @retval FALSE  If the TLV does not appear to be well-formed.
1236      *
1237      */
IsValid(void) const1238     bool IsValid(void) const { return GetLength() >= sizeof(mOui) && GetLength() <= sizeof(mOui) + sizeof(mAdvData); }
1239 
1240     /**
1241      * Returns the Vendor OUI value.
1242      *
1243      * @returns The Vendor OUI value.
1244      *
1245      */
GetOui(void) const1246     uint32_t GetOui(void) const { return BigEndian::ReadUint24(mOui); }
1247 
1248     /**
1249      * Sets the Vendor OUI value.
1250      *
1251      * @param[in]  aOui The Vendor OUI value.
1252      *
1253      */
SetOui(uint32_t aOui)1254     void SetOui(uint32_t aOui) { return BigEndian::WriteUint24(aOui, mOui); }
1255 
1256     /**
1257      * Returns the Adv Data length.
1258      *
1259      * @returns The AdvData length.
1260      *
1261      */
GetAdvDataLength(void) const1262     uint8_t GetAdvDataLength(void) const { return GetLength() - sizeof(mOui); }
1263 
1264     /**
1265      * Returns the Adv Data value.
1266      *
1267      * @returns A pointer to the Adv Data value.
1268      *
1269      */
GetAdvData(void) const1270     const uint8_t *GetAdvData(void) const { return mAdvData; }
1271 
1272     /**
1273      * Sets the Adv Data value.
1274      *
1275      * @param[in]  aAdvData        A pointer to the AdvData value.
1276      * @param[in]  aAdvDataLength  The length of AdvData in bytes.
1277      *
1278      */
SetAdvData(const uint8_t * aAdvData,uint8_t aAdvDataLength)1279     void SetAdvData(const uint8_t *aAdvData, uint8_t aAdvDataLength)
1280     {
1281         OT_ASSERT((aAdvData != nullptr) && (aAdvDataLength > 0) && (aAdvDataLength <= kAdvDataMaxLength));
1282 
1283         SetLength(aAdvDataLength + sizeof(mOui));
1284         memcpy(mAdvData, aAdvData, aAdvDataLength);
1285     }
1286 
1287 private:
1288     uint8_t mOui[3];
1289     uint8_t mAdvData[kAdvDataMaxLength];
1290 } OT_TOOL_PACKED_END;
1291 
1292 } // namespace MeshCoP
1293 
1294 } // namespace ot
1295 
1296 #endif // MESHCOP_TLVS_HPP_
1297