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 and methods for generating and processing Thread Network Layer TLVs.
32  */
33 
34 #ifndef THREAD_TLVS_HPP_
35 #define THREAD_TLVS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/encoding.hpp"
40 #include "common/message.hpp"
41 #include "common/tlvs.hpp"
42 #include "net/ip6_address.hpp"
43 #include "thread/mle.hpp"
44 #include "thread/mle_types.hpp"
45 
46 namespace ot {
47 
48 using ot::Encoding::BigEndian::HostSwap16;
49 using ot::Encoding::BigEndian::HostSwap32;
50 
51 // Thread 1.2.0 5.19.13 limits the number of IPv6 addresses should be [1, 15].
52 constexpr uint8_t kIp6AddressesNumMin = 1;
53 constexpr uint8_t kIp6AddressesNumMax = 15;
54 
55 /**
56  * This class implements Network Layer TLV generation and parsing.
57  *
58  */
59 OT_TOOL_PACKED_BEGIN
60 class ThreadTlv : public ot::Tlv
61 {
62 public:
63     /**
64      * Network Layer TLV Types.
65      *
66      */
67     enum Type : uint8_t
68     {
69         kTarget                = 0,  ///< Target EID TLV
70         kExtMacAddress         = 1,  ///< Extended MAC Address TLV
71         kRloc16                = 2,  ///< RLOC16 TLV
72         kMeshLocalEid          = 3,  ///< ML-EID TLV
73         kStatus                = 4,  ///< Status TLV
74         kLastTransactionTime   = 6,  ///< Time Since Last Transaction TLV
75         kRouterMask            = 7,  ///< Router Mask TLV
76         kNdOption              = 8,  ///< ND Option TLV
77         kNdData                = 9,  ///< ND Data TLV
78         kThreadNetworkData     = 10, ///< Thread Network Data TLV
79         kTimeout               = 11, ///< Timeout TLV
80         kNetworkName           = 12, ///< Network Name TLV
81         kIp6Addresses          = 14, ///< IPv6 Addresses TLV
82         kCommissionerSessionId = 15, ///< Commissioner Session ID TLV
83     };
84 
85     /**
86      * This method returns the Type value.
87      *
88      * @returns The Type value.
89      *
90      */
GetType(void) const91     Type GetType(void) const { return static_cast<Type>(ot::Tlv::GetType()); }
92 
93     /**
94      * This method sets the Type value.
95      *
96      * @param[in]  aType  The Type value.
97      *
98      */
SetType(Type aType)99     void SetType(Type aType) { ot::Tlv::SetType(static_cast<uint8_t>(aType)); }
100 
101 } OT_TOOL_PACKED_END;
102 
103 /**
104  * This class defines Target TLV constants and types.
105  *
106  */
107 typedef SimpleTlvInfo<ThreadTlv::kTarget, Ip6::Address> ThreadTargetTlv;
108 
109 /**
110  * This class defines Extended MAC Address TLV constants and types.
111  *
112  */
113 typedef SimpleTlvInfo<ThreadTlv::kExtMacAddress, Mac::ExtAddress> ThreadExtMacAddressTlv;
114 
115 /**
116  * This class defines RLOC16 TLV constants and types.
117  *
118  */
119 typedef UintTlvInfo<ThreadTlv::kRloc16, uint16_t> ThreadRloc16Tlv;
120 
121 /**
122  * This class defines ML-EID TLV constants and types.
123  *
124  */
125 typedef SimpleTlvInfo<ThreadTlv::kMeshLocalEid, Ip6::InterfaceIdentifier> ThreadMeshLocalEidTlv;
126 
127 /**
128  * This class defines Time Since Last Transaction TLV constants and types.
129  *
130  */
131 typedef UintTlvInfo<ThreadTlv::kLastTransactionTime, uint32_t> ThreadLastTransactionTimeTlv;
132 
133 /**
134  * This class defines Timeout TLV constants and types.
135  *
136  */
137 typedef UintTlvInfo<ThreadTlv::kTimeout, uint32_t> ThreadTimeoutTlv;
138 
139 /**
140  * This class defines Network Name TLV constants and types.
141  *
142  */
143 typedef TlvInfo<ThreadTlv::kNetworkName> ThreadNetworkNameTlv;
144 
145 /**
146  * This class defines Commissioner Session ID TLV constants and types.
147  *
148  */
149 typedef UintTlvInfo<ThreadTlv::kCommissionerSessionId, uint16_t> ThreadCommissionerSessionIdTlv;
150 
151 /**
152  * This class defines Status TLV constants and types.
153  *
154  */
155 class ThreadStatusTlv : public UintTlvInfo<ThreadTlv::kStatus, uint8_t>
156 {
157 public:
158     /**
159      * Status values.
160      *
161      */
162     enum Status : uint8_t
163     {
164         kSuccess               = 0, ///< Success.
165         kNoAddressAvailable    = 1, ///< No address available.
166         kTooFewRouters         = 2, ///< Address Solicit due to too few routers.
167         kHaveChildIdRequest    = 3, ///< Address Solicit due to child ID request.
168         kParentPartitionChange = 4, ///< Address Solicit due to parent partition change
169     };
170 
171     /**
172      * Multicast Listener Registration (MLR) Status values
173      *
174      */
175     enum MlrStatus
176     {
177         kMlrSuccess        = 0, ///< Successful (de)registration of all IPv6 addresses.
178         kMlrInvalid        = 2, ///< Invalid IPv6 address(es) in request.
179         kMlrNoPersistent   = 3, ///< This device does not support persistent registrations.
180         kMlrNoResources    = 4, ///< BBR resource shortage.
181         kMlrBbrNotPrimary  = 5, ///< BBR is not Primary at this moment.
182         kMlrGeneralFailure = 6, ///< Reason(s) for failure are not further specified.
183         kMlrStatusMax      = 6, ///< Max MLR status.
184     };
185 
186     /**
187      * Domain Unicast Address (DUA) Registration Status values
188      *
189      */
190     enum DuaStatus : uint8_t
191     {
192         kDuaSuccess        = 0, ///< Successful registration.
193         kDuaReRegister     = 1, ///< Registration was accepted but immediate reregistration is required to solve.
194         kDuaInvalid        = 2, ///< Registration rejected (Fatal): Target EID is not a valid DUA.
195         kDuaDuplicate      = 3, ///< Registration rejected (Fatal): DUA is already in use by another device.
196         kDuaNoResources    = 4, ///< Registration rejected (Non-fatal): Backbone Router Resource shortage.
197         kDuaNotPrimary     = 5, ///< Registration rejected (Non-fatal): Backbone Router is not primary at this moment.
198         kDuaGeneralFailure = 6, ///< Registration failure (Non-fatal): Reason(s) not further specified.
199     };
200 };
201 
202 /**
203  * This class implements Router Mask TLV generation and parsing.
204  *
205  */
206 class ThreadRouterMaskTlv : public ThreadTlv, public TlvInfo<ThreadTlv::kRouterMask>
207 {
208 public:
209     /**
210      * This method initializes the TLV.
211      *
212      */
Init(void)213     void Init(void)
214     {
215         SetType(kRouterMask);
216         SetLength(sizeof(*this) - sizeof(ThreadTlv));
217         mAssignedRouterIdMask.Clear();
218     }
219 
220     /**
221      * This method indicates whether or not the TLV appears to be well-formed.
222      *
223      * @retval TRUE   If the TLV appears to be well-formed.
224      * @retval FALSE  If the TLV does not appear to be well-formed.
225      *
226      */
IsValid(void) const227     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(ThreadTlv); }
228 
229     /**
230      * This method returns the ID Sequence value.
231      *
232      * @returns The ID Sequence value.
233      *
234      */
GetIdSequence(void) const235     uint8_t GetIdSequence(void) const { return mIdSequence; }
236 
237     /**
238      * This method sets the ID Sequence value.
239      *
240      * @param[in]  aSequence  The ID Sequence value.
241      *
242      */
SetIdSequence(uint8_t aSequence)243     void SetIdSequence(uint8_t aSequence) { mIdSequence = aSequence; }
244 
245     /**
246      * This method gets the Assigned Router ID Mask.
247      *
248      * @returns The Assigned Router ID Mask.
249      *
250      */
GetAssignedRouterIdMask(void) const251     const Mle::RouterIdSet &GetAssignedRouterIdMask(void) const { return mAssignedRouterIdMask; }
252 
253     /**
254      * This method sets the Assigned Router ID Mask.
255      *
256      * @param[in]  aRouterIdSet A reference to the Assigned Router ID Mask.
257      *
258      */
SetAssignedRouterIdMask(const Mle::RouterIdSet & aRouterIdSet)259     void SetAssignedRouterIdMask(const Mle::RouterIdSet &aRouterIdSet) { mAssignedRouterIdMask = aRouterIdSet; }
260 
261 private:
262     uint8_t          mIdSequence;
263     Mle::RouterIdSet mAssignedRouterIdMask;
264 };
265 
266 /**
267  * This class implements Thread Network Data TLV generation and parsing.
268  *
269  */
270 OT_TOOL_PACKED_BEGIN
271 class ThreadNetworkDataTlv : public ThreadTlv, public TlvInfo<ThreadTlv::kThreadNetworkData>
272 {
273 public:
274     /**
275      * This method initializes the TLV.
276      *
277      */
Init(void)278     void Init(void)
279     {
280         SetType(kThreadNetworkData);
281         SetLength(0);
282     }
283 
284     /**
285      * This method overrides same method of the base class
286      *
287      * @retval TRUE  the TLV appears to be well-formed.
288      *
289      */
IsValid(void) const290     bool IsValid(void) const { return true; }
291 
292     /**
293      * This method returns a pointer to the Network Data TLVs.
294      *
295      * @returns A pointer to the Network Data TLVs.
296      *
297      */
GetTlvs(void)298     uint8_t *GetTlvs(void) { return mTlvs; }
299 
300 private:
301     static constexpr uint8_t kMaxSize = 255;
302 
303     uint8_t mTlvs[kMaxSize];
304 } OT_TOOL_PACKED_END;
305 
306 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
307 
308 /**
309  * This class implements IPv6 Addresses TLV generation and parsing.
310  *
311  */
312 OT_TOOL_PACKED_BEGIN
313 class Ip6AddressesTlv : public ThreadTlv, public TlvInfo<ThreadTlv::kIp6Addresses>
314 {
315 public:
316     /**
317      * This method initializes the TLV.
318      *
319      */
Init(void)320     void Init(void) { SetType(kIp6Addresses); }
321 
322     /**
323      * This method indicates whether or not the TLV appears to be well-formed.
324      *
325      * @retval TRUE   If the TLV appears to be well-formed.
326      * @retval FALSE  If the TLV does not appear to be well-formed.
327      *
328      */
IsValid(void) const329     bool IsValid(void) const
330     {
331         return GetLength() >= sizeof(Ip6::Address) * kIp6AddressesNumMin &&
332                GetLength() <= sizeof(Ip6::Address) * kIp6AddressesNumMax && (GetLength() % sizeof(Ip6::Address)) == 0;
333     }
334 
335     /**
336      * This method returns a pointer to the IPv6 address entry.
337      *
338      * @param[in]  aIndex  The index into the IPv6 address list.
339      *
340      * @returns A reference to the IPv6 address.
341      *
342      */
GetIp6Address(uint8_t aIndex) const343     const Ip6::Address &GetIp6Address(uint8_t aIndex) const
344     {
345         return *reinterpret_cast<const Ip6::Address *>(GetValue() + (aIndex * sizeof(Ip6::Address)));
346     }
347 } OT_TOOL_PACKED_END;
348 
349 #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
350 
351 } // namespace ot
352 
353 #endif // THREAD_TLVS_HPP_
354