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 a Thread `Child`.
32  */
33 
34 #ifndef CHILD_HPP_
35 #define CHILD_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "thread/neighbor.hpp"
40 
41 namespace ot {
42 
43 #if OPENTHREAD_FTD
44 
45 #if OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD < 2
46 #error OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD should be at least set to 2.
47 #endif
48 
49 /**
50  * Represents a Thread Child.
51  *
52  */
53 class Child : public Neighbor,
54               public IndirectSender::ChildInfo,
55               public DataPollHandler::ChildInfo
56 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
57     ,
58               public CslTxScheduler::ChildInfo
59 #endif
60 {
61 public:
62     static constexpr uint8_t kMaxRequestTlvs = 6;
63 
64     /**
65      * Maximum number of registered IPv6 addresses per child (excluding the mesh-local EID).
66      *
67      */
68     static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1;
69 
70     /**
71      * Represents the iterator for registered IPv6 address list of an MTD child.
72      *
73      */
74     typedef otChildIp6AddressIterator AddressIterator;
75 
76     /**
77      * The initial value for an `AddressIterator`.
78      *
79      */
80     static constexpr AddressIterator kAddressIteratorInit = OT_CHILD_IP6_ADDRESS_ITERATOR_INIT;
81 
82     /**
83      * Represents diagnostic information for a Thread Child.
84      *
85      */
86     class Info : public otChildInfo, public Clearable<Info>
87     {
88     public:
89         /**
90          * Sets the `Info` instance from a given `Child`.
91          *
92          * @param[in] aChild   A neighbor.
93          *
94          */
95         void SetFrom(const Child &aChild);
96     };
97 
98     /**
99      * Represents an IPv6 address entry registered by an MTD child.
100      *
101      */
102     class Ip6AddrEntry : public Ip6::Address
103     {
104     public:
105         /**
106          * Indicates whether the entry matches a given IPv6 address.
107          *
108          * @param[in] aAddress   The IPv6 address.
109          *
110          * @retval TRUE   The entry matches @p aAddress.
111          * @retval FALSE  The entry does not match @p aAddress.
112          *
113          */
Matches(const Ip6::Address & aAddress) const114         bool Matches(const Ip6::Address &aAddress) const { return (*this == aAddress); }
115 
116 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
117         /**
118          * Gets the MLR state of the IPv6 address entry.
119          *
120          * @param[in] aChild  The child owning this address entry.
121          *
122          * @returns The MLR state of IPv6 address entry.
123          *
124          */
125         MlrState GetMlrState(const Child &aChild) const;
126 
127         /**
128          * Sets the MLR state of the IPv6 address entry.
129          *
130          * @param[in] aState    The MLR state.
131          * @param[in] aChild    The child owning this address entry.
132          *
133          */
134         void SetMlrState(MlrState aState, Child &aChild);
135 #endif
136     };
137 
138     /**
139      * Represents an array of IPv6 address entries registered by an MTD child.
140      *
141      * This array does not include the mesh-local EID.
142      *
143      */
144     typedef Array<Ip6AddrEntry, kNumIp6Addresses> Ip6AddressArray;
145 
146     /**
147      * Initializes the `Child` object.
148      *
149      * @param[in] aInstance  A reference to OpenThread instance.
150      *
151      */
Init(Instance & aInstance)152     void Init(Instance &aInstance) { Neighbor::Init(aInstance); }
153 
154     /**
155      * Clears the child entry.
156      *
157      */
158     void Clear(void);
159 
160     /**
161      * Clears the IPv6 address list for the child.
162      *
163      */
164     void ClearIp6Addresses(void);
165 
166     /**
167      * Sets the device mode flags.
168      *
169      * @param[in]  aMode  The device mode flags.
170      *
171      */
172     void SetDeviceMode(Mle::DeviceMode aMode);
173 
174     /**
175      * Gets the mesh-local IPv6 address.
176      *
177      * @param[out]   aAddress            A reference to an IPv6 address to provide address (if any).
178      *
179      * @retval kErrorNone      Successfully found the mesh-local address and updated @p aAddress.
180      * @retval kErrorNotFound  No mesh-local IPv6 address in the IPv6 address list.
181      *
182      */
183     Error GetMeshLocalIp6Address(Ip6::Address &aAddress) const;
184 
185     /**
186      * Returns the Mesh Local Interface Identifier.
187      *
188      * @returns The Mesh Local Interface Identifier.
189      *
190      */
GetMeshLocalIid(void) const191     const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; }
192 
193     /**
194      * Gets an array of registered IPv6 address entries by the child.
195      *
196      * The array does not include the mesh-local EID. The ML-EID can retrieved using  `GetMeshLocalIp6Address()`.
197      *
198      * @returns The array of registered IPv6 addresses by the child.
199      *
200      */
GetIp6Addresses(void) const201     const Ip6AddressArray &GetIp6Addresses(void) const { return mIp6Addresses; }
202 
203     /**
204      * Gets an array of registered IPv6 address entries by the child.
205      *
206      * The array does not include the mesh-local EID. The ML-EID can retrieved using  `GetMeshLocalIp6Address()`.
207      *
208      * @returns The array of registered IPv6 addresses by the child.
209      *
210      */
GetIp6Addresses(void)211     Ip6AddressArray &GetIp6Addresses(void) { return mIp6Addresses; }
212 
213     /**
214      * Iterates over all registered IPv6 addresses (using an iterator).
215      *
216      * @param[in,out]  aIterator  The iterator to use. On success the iterator will be updated.
217      *                            To get the first IPv6 address the iterator should be set to `kAddressIteratorInit`
218      * @param[out]     aAddress   A reference to an IPv6 address to return the address.
219      *
220      * @retval kErrorNone        Successfully got the next IPv6 address. @p aIterator and @p aAddress are updated.
221      * @retval kErrorNotFound    No more address.
222      *
223      */
224     Error GetNextIp6Address(AddressIterator &aIterator, Ip6::Address &aAddress) const;
225 
226     /**
227      * Adds an IPv6 address to the list.
228      *
229      * @param[in]  aAddress           A reference to IPv6 address to be added.
230      *
231      * @retval kErrorNone          Successfully added the new address.
232      * @retval kErrorAlready       Address is already in the list.
233      * @retval kErrorNoBufs        Already at maximum number of addresses. No entry available to add the new address.
234      * @retval kErrorInvalidArgs   Address is invalid (it is the Unspecified Address).
235      *
236      */
237     Error AddIp6Address(const Ip6::Address &aAddress);
238 
239     /**
240      * Removes an IPv6 address from the list.
241      *
242      * @param[in]  aAddress               A reference to IPv6 address to be removed.
243      *
244      * @retval kErrorNone             Successfully removed the address.
245      * @retval kErrorNotFound         Address was not found in the list.
246      * @retval kErrorInvalidArgs      Address is invalid (it is the Unspecified Address).
247      *
248      */
249     Error RemoveIp6Address(const Ip6::Address &aAddress);
250 
251     /**
252      * Indicates whether an IPv6 address is in the list of IPv6 addresses of the child.
253      *
254      * @param[in]  aAddress   A reference to IPv6 address.
255      *
256      * @retval TRUE           The address exists on the list.
257      * @retval FALSE          Address was not found in the list.
258      *
259      */
260     bool HasIp6Address(const Ip6::Address &aAddress) const;
261 
262 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
263     /**
264      * Retrieves the Domain Unicast Address registered by the child.
265      *
266      * @param[out] aAddress    A reference to return the DUA address.
267      *
268      * @retval kErrorNone      Successfully retrieved the DUA address, @p aAddress is updated.
269      * @retval kErrorNotFound  Could not find any DUA address.
270      *
271      */
272     Error GetDomainUnicastAddress(Ip6::Address &aAddress) const;
273 #endif
274 
275     /**
276      * Gets the child timeout.
277      *
278      * @returns The child timeout.
279      *
280      */
GetTimeout(void) const281     uint32_t GetTimeout(void) const { return mTimeout; }
282 
283     /**
284      * Sets the child timeout.
285      *
286      * @param[in]  aTimeout  The child timeout.
287      *
288      */
SetTimeout(uint32_t aTimeout)289     void SetTimeout(uint32_t aTimeout) { mTimeout = aTimeout; }
290 
291     /**
292      * Gets the network data version.
293      *
294      * @returns The network data version.
295      *
296      */
GetNetworkDataVersion(void) const297     uint8_t GetNetworkDataVersion(void) const { return mNetworkDataVersion; }
298 
299     /**
300      * Sets the network data version.
301      *
302      * @param[in]  aVersion  The network data version.
303      *
304      */
SetNetworkDataVersion(uint8_t aVersion)305     void SetNetworkDataVersion(uint8_t aVersion) { mNetworkDataVersion = aVersion; }
306 
307     /**
308      * Generates a new challenge value to use during a child attach.
309      *
310      */
GenerateChallenge(void)311     void GenerateChallenge(void) { mAttachChallenge.GenerateRandom(); }
312 
313     /**
314      * Gets the current challenge value used during attach.
315      *
316      * @returns The current challenge value.
317      *
318      */
GetChallenge(void) const319     const Mle::TxChallenge &GetChallenge(void) const { return mAttachChallenge; }
320 
321     /**
322      * Clears the requested TLV list.
323      *
324      */
ClearRequestTlvs(void)325     void ClearRequestTlvs(void) { memset(mRequestTlvs, Mle::Tlv::kInvalid, sizeof(mRequestTlvs)); }
326 
327     /**
328      * Returns the requested TLV at index @p aIndex.
329      *
330      * @param[in]  aIndex  The index into the requested TLV list.
331      *
332      * @returns The requested TLV at index @p aIndex.
333      *
334      */
GetRequestTlv(uint8_t aIndex) const335     uint8_t GetRequestTlv(uint8_t aIndex) const { return mRequestTlvs[aIndex]; }
336 
337     /**
338      * Sets the requested TLV at index @p aIndex.
339      *
340      * @param[in]  aIndex  The index into the requested TLV list.
341      * @param[in]  aType   The TLV type.
342      *
343      */
SetRequestTlv(uint8_t aIndex,uint8_t aType)344     void SetRequestTlv(uint8_t aIndex, uint8_t aType) { mRequestTlvs[aIndex] = aType; }
345 
346     /**
347      * Returns the supervision interval (in seconds).
348      *
349      * @returns The supervision interval (in seconds).
350      *
351      */
GetSupervisionInterval(void) const352     uint16_t GetSupervisionInterval(void) const { return mSupervisionInterval; }
353 
354     /**
355      * Sets the supervision interval.
356      *
357      * @param[in] aInterval  The supervision interval (in seconds).
358      *
359      */
SetSupervisionInterval(uint16_t aInterval)360     void SetSupervisionInterval(uint16_t aInterval) { mSupervisionInterval = aInterval; }
361 
362     /**
363      * Increments the number of seconds since last supervision of the child.
364      *
365      */
IncrementSecondsSinceLastSupervision(void)366     void IncrementSecondsSinceLastSupervision(void) { mSecondsSinceSupervision++; }
367 
368     /**
369      * Returns the number of seconds since last supervision of the child (last message to the child)
370      *
371      * @returns Number of seconds since last supervision of the child.
372      *
373      */
GetSecondsSinceLastSupervision(void) const374     uint16_t GetSecondsSinceLastSupervision(void) const { return mSecondsSinceSupervision; }
375 
376     /**
377      * Resets the number of seconds since last supervision of the child to zero.
378      *
379      */
ResetSecondsSinceLastSupervision(void)380     void ResetSecondsSinceLastSupervision(void) { mSecondsSinceSupervision = 0; }
381 
382 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
383     /**
384      * Returns if the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
385      *
386      * @param[in] aAddress  The IPv6 address.
387      *
388      * @retval true   If the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
389      * @retval false  If the Child does not have IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
390      *
391      */
392     bool HasMlrRegisteredAddress(const Ip6::Address &aAddress) const;
393 
394     /**
395      * Returns if the Child has any IPv6 address of MLR state `kMlrStateRegistered`.
396      *
397      * @retval true   If the Child has any IPv6 address of MLR state `kMlrStateRegistered`.
398      * @retval false  If the Child does not have any IPv6 address of MLR state `kMlrStateRegistered`.
399      *
400      */
HasAnyMlrRegisteredAddress(void) const401     bool HasAnyMlrRegisteredAddress(void) const { return mMlrRegisteredMask.HasAny(); }
402 
403     /**
404      * Returns if the Child has any IPv6 address of MLR state `kMlrStateToRegister`.
405      *
406      * @retval true   If the Child has any IPv6 address of MLR state `kMlrStateToRegister`.
407      * @retval false  If the Child does not have any IPv6 address of MLR state `kMlrStateToRegister`.
408      *
409      */
HasAnyMlrToRegisterAddress(void) const410     bool HasAnyMlrToRegisterAddress(void) const { return mMlrToRegisterMask.HasAny(); }
411 #endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
412 
413 private:
414     typedef BitVector<kNumIp6Addresses> ChildIp6AddressMask;
415 
416     uint32_t mTimeout;
417 
418     Ip6::InterfaceIdentifier mMeshLocalIid;
419     Ip6AddressArray          mIp6Addresses;
420 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
421     ChildIp6AddressMask mMlrToRegisterMask;
422     ChildIp6AddressMask mMlrRegisteredMask;
423 #endif
424 
425     uint8_t mNetworkDataVersion;
426 
427     union
428     {
429         uint8_t          mRequestTlvs[kMaxRequestTlvs];
430         Mle::TxChallenge mAttachChallenge;
431     };
432 
433     uint16_t mSupervisionInterval;
434     uint16_t mSecondsSinceSupervision;
435 
436     static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < 8192, "mQueuedMessageCount cannot fit max required!");
437 };
438 
439 DefineCoreType(otChildInfo, Child::Info);
440 
441 #endif // OPENTHREAD_FTD
442 
443 } // namespace ot
444 
445 #endif // CHILD_HPP_
446