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 /**
46  * Represents a Thread Child.
47  *
48  */
49 class Child : public Neighbor,
50               public IndirectSender::ChildInfo,
51               public DataPollHandler::ChildInfo
52 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
53     ,
54               public CslTxScheduler::ChildInfo
55 #endif
56 {
57     class AddressIteratorBuilder;
58 
59 public:
60     static constexpr uint8_t kMaxRequestTlvs = 6;
61 
62     /**
63      * Represents diagnostic information for a Thread Child.
64      *
65      */
66     class Info : public otChildInfo, public Clearable<Info>
67     {
68     public:
69         /**
70          * Sets the `Info` instance from a given `Child`.
71          *
72          * @param[in] aChild   A neighbor.
73          *
74          */
75         void SetFrom(const Child &aChild);
76     };
77 
78     /**
79      * Defines an iterator used to go through IPv6 address entries of a child.
80      *
81      */
82     class AddressIterator : public Unequatable<AddressIterator>
83     {
84         friend class AddressIteratorBuilder;
85 
86     public:
87         /**
88          * Represents an index indicating the current IPv6 address entry to which the iterator is pointing.
89          *
90          */
91         typedef otChildIp6AddressIterator Index;
92 
93         /**
94          * Initializes the iterator associated with a given `Child` starting from beginning of the
95          * IPv6 address list.
96          *
97          * @param[in] aChild    A reference to a child entry.
98          * @param[in] aFilter   An IPv6 address type filter restricting iterator to certain type of addresses.
99          *
100          */
AddressIterator(const Child & aChild,Ip6::Address::TypeFilter aFilter=Ip6::Address::kTypeAny)101         explicit AddressIterator(const Child &aChild, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny)
102             : AddressIterator(aChild, 0, aFilter)
103         {
104         }
105 
106         /**
107          * Initializes the iterator associated with a given `Child` starting from a given index
108          *
109          * @param[in]  aChild   A reference to the child entry.
110          * @param[in]  aIndex   An index (`Index`) with which to initialize the iterator.
111          * @param[in]  aFilter  An IPv6 address type filter restricting iterator to certain type of addresses.
112          *
113          */
AddressIterator(const Child & aChild,Index aIndex,Ip6::Address::TypeFilter aFilter=Ip6::Address::kTypeAny)114         AddressIterator(const Child &aChild, Index aIndex, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny)
115             : mChild(aChild)
116             , mFilter(aFilter)
117             , mIndex(aIndex)
118         {
119             Update();
120         }
121 
122         /**
123          * Converts the iterator into an index.
124          *
125          * @returns An index corresponding to the iterator.
126          *
127          */
GetAsIndex(void) const128         Index GetAsIndex(void) const { return mIndex; }
129 
130         /**
131          * Gets the iterator's associated `Child` entry.
132          *
133          * @returns The associated child entry.
134          *
135          */
GetChild(void) const136         const Child &GetChild(void) const { return mChild; }
137 
138         /**
139          * Gets the current `Child` IPv6 Address to which the iterator is pointing.
140          *
141          * @returns  A pointer to the associated IPv6 Address, or `nullptr` if iterator is done.
142          *
143          */
144         const Ip6::Address *GetAddress(void) const;
145 
146         /**
147          * Indicates whether the iterator has reached end of the list.
148          *
149          * @retval TRUE   There are no more entries in the list (reached end of the list).
150          * @retval FALSE  The current entry is valid.
151          *
152          */
IsDone(void) const153         bool IsDone(void) const { return (mIndex >= kMaxIndex); }
154 
155         /**
156          * Overloads `++` operator (pre-increment) to advance the iterator.
157          *
158          * The iterator is moved to point to the next `Address` entry.  If there are no more `Ip6::Address` entries
159          * `IsDone()` returns `true`.
160          *
161          */
operator ++(void)162         void operator++(void) { mIndex++, Update(); }
163 
164         /**
165          * Overloads `++` operator (post-increment) to advance the iterator.
166          *
167          * The iterator is moved to point to the next `Address` entry.  If there are no more `Ip6::Address` entries
168          *  `IsDone()` returns `true`.
169          *
170          */
operator ++(int)171         void operator++(int) { mIndex++, Update(); }
172 
173         /**
174          * Overloads the `*` dereference operator and gets a reference to `Ip6::Address` to which the
175          * iterator is currently pointing.
176          *
177          * MUST be used when the iterator is not done (i.e., `IsDone()` returns `false`).
178          *
179          * @returns A reference to the `Ip6::Address` entry currently pointed by the iterator.
180          *
181          */
operator *(void) const182         const Ip6::Address &operator*(void) const { return *GetAddress(); }
183 
184         /**
185          * Overloads operator `==` to evaluate whether or not two `Iterator` instances are equal.
186          *
187          * MUST be used when the two iterators are associated with the same `Child` entry.
188          *
189          * @param[in]  aOther  The other `Iterator` to compare with.
190          *
191          * @retval TRUE   If the two `Iterator` objects are equal.
192          * @retval FALSE  If the two `Iterator` objects are not equal.
193          *
194          */
operator ==(const AddressIterator & aOther) const195         bool operator==(const AddressIterator &aOther) const { return (mIndex == aOther.mIndex); }
196 
197     private:
198         enum IteratorType : uint8_t
199         {
200             kEndIterator,
201         };
202 
203         static constexpr uint16_t kMaxIndex = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
204 
AddressIterator(const Child & aChild,IteratorType)205         AddressIterator(const Child &aChild, IteratorType)
206             : mChild(aChild)
207             , mIndex(kMaxIndex)
208         {
209         }
210 
211         void Update(void);
212 
213         const Child             &mChild;
214         Ip6::Address::TypeFilter mFilter;
215         Index                    mIndex;
216         Ip6::Address             mMeshLocalAddress;
217     };
218 
219     /**
220      * Initializes the `Child` object.
221      *
222      * @param[in] aInstance  A reference to OpenThread instance.
223      *
224      */
Init(Instance & aInstance)225     void Init(Instance &aInstance) { Neighbor::Init(aInstance); }
226 
227     /**
228      * Clears the child entry.
229      *
230      */
231     void Clear(void);
232 
233     /**
234      * Clears the IPv6 address list for the child.
235      *
236      */
237     void ClearIp6Addresses(void);
238 
239     /**
240      * Sets the device mode flags.
241      *
242      * @param[in]  aMode  The device mode flags.
243      *
244      */
245     void SetDeviceMode(Mle::DeviceMode aMode);
246 
247     /**
248      * Gets the mesh-local IPv6 address.
249      *
250      * @param[out]   aAddress            A reference to an IPv6 address to provide address (if any).
251      *
252      * @retval kErrorNone      Successfully found the mesh-local address and updated @p aAddress.
253      * @retval kErrorNotFound  No mesh-local IPv6 address in the IPv6 address list.
254      *
255      */
256     Error GetMeshLocalIp6Address(Ip6::Address &aAddress) const;
257 
258     /**
259      * Returns the Mesh Local Interface Identifier.
260      *
261      * @returns The Mesh Local Interface Identifier.
262      *
263      */
GetMeshLocalIid(void) const264     const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; }
265 
266     /**
267      * Enables range-based `for` loop iteration over all (or a subset of) IPv6 addresses.
268      *
269      * Should be used as follows: to iterate over all addresses
270      *
271      *     for (const Ip6::Address &address : child.IterateIp6Addresses()) { ... }
272      *
273      * or to iterate over a subset of IPv6 addresses determined by a given address type filter
274      *
275      *     for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticast)) { ... }
276      *
277      * @param[in] aFilter  An IPv6 address type filter restricting iteration to certain type of addresses (default is
278      *                     to accept any address type).
279      *
280      * @returns An IteratorBuilder instance.
281      *
282      */
IterateIp6Addresses(Ip6::Address::TypeFilter aFilter=Ip6::Address::kTypeAny) const283     AddressIteratorBuilder IterateIp6Addresses(Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) const
284     {
285         return AddressIteratorBuilder(*this, aFilter);
286     }
287 
288     /**
289      * Adds an IPv6 address to the list.
290      *
291      * @param[in]  aAddress           A reference to IPv6 address to be added.
292      *
293      * @retval kErrorNone          Successfully added the new address.
294      * @retval kErrorAlready       Address is already in the list.
295      * @retval kErrorNoBufs        Already at maximum number of addresses. No entry available to add the new address.
296      * @retval kErrorInvalidArgs   Address is invalid (it is the Unspecified Address).
297      *
298      */
299     Error AddIp6Address(const Ip6::Address &aAddress);
300 
301     /**
302      * Removes an IPv6 address from the list.
303      *
304      * @param[in]  aAddress               A reference to IPv6 address to be removed.
305      *
306      * @retval kErrorNone             Successfully removed the address.
307      * @retval kErrorNotFound         Address was not found in the list.
308      * @retval kErrorInvalidArgs      Address is invalid (it is the Unspecified Address).
309      *
310      */
311     Error RemoveIp6Address(const Ip6::Address &aAddress);
312 
313     /**
314      * Indicates whether an IPv6 address is in the list of IPv6 addresses of the child.
315      *
316      * @param[in]  aAddress   A reference to IPv6 address.
317      *
318      * @retval TRUE           The address exists on the list.
319      * @retval FALSE          Address was not found in the list.
320      *
321      */
322     bool HasIp6Address(const Ip6::Address &aAddress) const;
323 
324 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
325     /**
326      * Retrieves the Domain Unicast Address registered by the child.
327      *
328      * @returns A pointer to Domain Unicast Address registered by the child if there is.
329      *
330      */
331     const Ip6::Address *GetDomainUnicastAddress(void) const;
332 #endif
333 
334     /**
335      * Gets the child timeout.
336      *
337      * @returns The child timeout.
338      *
339      */
GetTimeout(void) const340     uint32_t GetTimeout(void) const { return mTimeout; }
341 
342     /**
343      * Sets the child timeout.
344      *
345      * @param[in]  aTimeout  The child timeout.
346      *
347      */
SetTimeout(uint32_t aTimeout)348     void SetTimeout(uint32_t aTimeout) { mTimeout = aTimeout; }
349 
350     /**
351      * Gets the network data version.
352      *
353      * @returns The network data version.
354      *
355      */
GetNetworkDataVersion(void) const356     uint8_t GetNetworkDataVersion(void) const { return mNetworkDataVersion; }
357 
358     /**
359      * Sets the network data version.
360      *
361      * @param[in]  aVersion  The network data version.
362      *
363      */
SetNetworkDataVersion(uint8_t aVersion)364     void SetNetworkDataVersion(uint8_t aVersion) { mNetworkDataVersion = aVersion; }
365 
366     /**
367      * Generates a new challenge value to use during a child attach.
368      *
369      */
GenerateChallenge(void)370     void GenerateChallenge(void) { mAttachChallenge.GenerateRandom(); }
371 
372     /**
373      * Gets the current challenge value used during attach.
374      *
375      * @returns The current challenge value.
376      *
377      */
GetChallenge(void) const378     const Mle::TxChallenge &GetChallenge(void) const { return mAttachChallenge; }
379 
380     /**
381      * Clears the requested TLV list.
382      *
383      */
ClearRequestTlvs(void)384     void ClearRequestTlvs(void) { memset(mRequestTlvs, Mle::Tlv::kInvalid, sizeof(mRequestTlvs)); }
385 
386     /**
387      * Returns the requested TLV at index @p aIndex.
388      *
389      * @param[in]  aIndex  The index into the requested TLV list.
390      *
391      * @returns The requested TLV at index @p aIndex.
392      *
393      */
GetRequestTlv(uint8_t aIndex) const394     uint8_t GetRequestTlv(uint8_t aIndex) const { return mRequestTlvs[aIndex]; }
395 
396     /**
397      * Sets the requested TLV at index @p aIndex.
398      *
399      * @param[in]  aIndex  The index into the requested TLV list.
400      * @param[in]  aType   The TLV type.
401      *
402      */
SetRequestTlv(uint8_t aIndex,uint8_t aType)403     void SetRequestTlv(uint8_t aIndex, uint8_t aType) { mRequestTlvs[aIndex] = aType; }
404 
405     /**
406      * Returns the supervision interval (in seconds).
407      *
408      * @returns The supervision interval (in seconds).
409      *
410      */
GetSupervisionInterval(void) const411     uint16_t GetSupervisionInterval(void) const { return mSupervisionInterval; }
412 
413     /**
414      * Sets the supervision interval.
415      *
416      * @param[in] aInterval  The supervision interval (in seconds).
417      *
418      */
SetSupervisionInterval(uint16_t aInterval)419     void SetSupervisionInterval(uint16_t aInterval) { mSupervisionInterval = aInterval; }
420 
421     /**
422      * Increments the number of seconds since last supervision of the child.
423      *
424      */
IncrementSecondsSinceLastSupervision(void)425     void IncrementSecondsSinceLastSupervision(void) { mSecondsSinceSupervision++; }
426 
427     /**
428      * Returns the number of seconds since last supervision of the child (last message to the child)
429      *
430      * @returns Number of seconds since last supervision of the child.
431      *
432      */
GetSecondsSinceLastSupervision(void) const433     uint16_t GetSecondsSinceLastSupervision(void) const { return mSecondsSinceSupervision; }
434 
435     /**
436      * Resets the number of seconds since last supervision of the child to zero.
437      *
438      */
ResetSecondsSinceLastSupervision(void)439     void ResetSecondsSinceLastSupervision(void) { mSecondsSinceSupervision = 0; }
440 
441 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
442     /**
443      * Returns MLR state of an IPv6 multicast address.
444      *
445      * @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`.
446      *
447      * @param[in] aAddress  The IPv6 multicast address.
448      *
449      * @returns MLR state of the IPv6 multicast address.
450      *
451      */
452     MlrState GetAddressMlrState(const Ip6::Address &aAddress) const;
453 
454     /**
455      * Sets MLR state of an IPv6 multicast address.
456      *
457      * @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`.
458      *
459      * @param[in] aAddress  The IPv6 multicast address.
460      * @param[in] aState    The target MLR state.
461      *
462      */
463     void SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState);
464 
465     /**
466      * Returns if the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
467      *
468      * @param[in] aAddress  The IPv6 address.
469      *
470      * @retval true   If the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
471      * @retval false  If the Child does not have IPv6 address @p aAddress of MLR state `kMlrStateRegistered`.
472      *
473      */
474     bool HasMlrRegisteredAddress(const Ip6::Address &aAddress) const;
475 
476     /**
477      * Returns if the Child has any IPv6 address of MLR state `kMlrStateRegistered`.
478      *
479      * @retval true   If the Child has any IPv6 address of MLR state `kMlrStateRegistered`.
480      * @retval false  If the Child does not have any IPv6 address of MLR state `kMlrStateRegistered`.
481      *
482      */
HasAnyMlrRegisteredAddress(void) const483     bool HasAnyMlrRegisteredAddress(void) const { return mMlrRegisteredMask.HasAny(); }
484 
485     /**
486      * Returns if the Child has any IPv6 address of MLR state `kMlrStateToRegister`.
487      *
488      * @retval true   If the Child has any IPv6 address of MLR state `kMlrStateToRegister`.
489      * @retval false  If the Child does not have any IPv6 address of MLR state `kMlrStateToRegister`.
490      *
491      */
HasAnyMlrToRegisterAddress(void) const492     bool HasAnyMlrToRegisterAddress(void) const { return mMlrToRegisterMask.HasAny(); }
493 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
494 
495 private:
496 #if OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD < 2
497 #error OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD should be at least set to 2.
498 #endif
499 
500     static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1;
501 
502     typedef BitVector<kNumIp6Addresses> ChildIp6AddressMask;
503 
504     class AddressIteratorBuilder
505     {
506     public:
AddressIteratorBuilder(const Child & aChild,Ip6::Address::TypeFilter aFilter)507         AddressIteratorBuilder(const Child &aChild, Ip6::Address::TypeFilter aFilter)
508             : mChild(aChild)
509             , mFilter(aFilter)
510         {
511         }
512 
begin(void)513         AddressIterator begin(void) { return AddressIterator(mChild, mFilter); }
end(void)514         AddressIterator end(void) { return AddressIterator(mChild, AddressIterator::kEndIterator); }
515 
516     private:
517         const Child             &mChild;
518         Ip6::Address::TypeFilter mFilter;
519     };
520 
521     Ip6::InterfaceIdentifier mMeshLocalIid;                 ///< IPv6 address IID for mesh-local address
522     Ip6::Address             mIp6Address[kNumIp6Addresses]; ///< Registered IPv6 addresses
523     uint32_t                 mTimeout;                      ///< Child timeout
524 
525 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
526     ChildIp6AddressMask mMlrToRegisterMask;
527     ChildIp6AddressMask mMlrRegisteredMask;
528 #endif
529 
530     uint8_t mNetworkDataVersion; ///< Current Network Data version
531 
532     union
533     {
534         uint8_t          mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs
535         Mle::TxChallenge mAttachChallenge;              ///< The challenge value
536     };
537 
538     uint16_t mSupervisionInterval;     // Supervision interval for the child (in sec).
539     uint16_t mSecondsSinceSupervision; // Number of seconds since last supervision of the child.
540 
541     static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < 8192, "mQueuedMessageCount cannot fit max required!");
542 };
543 
544 DefineCoreType(otChildInfo, Child::Info);
545 
546 #endif // OPENTHREAD_FTD
547 
548 } // namespace ot
549 
550 #endif // CHILD_HPP_
551