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 manipulating Thread Network Data managed by the Thread Leader.
32  */
33 
34 #ifndef NETWORK_DATA_LEADER_FTD_HPP_
35 #define NETWORK_DATA_LEADER_FTD_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_FTD
40 
41 #include <stdint.h>
42 
43 #include "coap/coap.hpp"
44 #include "common/non_copyable.hpp"
45 #include "common/timer.hpp"
46 #include "net/ip6_address.hpp"
47 #include "thread/mle_router.hpp"
48 #include "thread/network_data.hpp"
49 
50 namespace ot {
51 
52 namespace NetworkData {
53 
54 /**
55  * @addtogroup core-netdata-leader
56  *
57  * @brief
58  *   This module includes definitions for manipulating Thread Network Data managed by the Thread Leader.
59  *
60  * @{
61  *
62  */
63 
64 /**
65  * This class implements the Thread Network Data maintained by the Leader.
66  *
67  */
68 class Leader : public LeaderBase, private NonCopyable
69 {
70 public:
71     /**
72      * This enumeration defines the match mode constants to compare two RLOC16 values.
73      *
74      */
75     enum MatchMode : uint8_t
76     {
77         kMatchModeRloc16,   ///< Perform exact RLOC16 match.
78         kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children).
79     };
80 
81     /**
82      * This constructor initializes the object.
83      *
84      * @param[in]  aInstance     A reference to the OpenThread instance.
85      *
86      */
87     explicit Leader(Instance &aInstance);
88 
89     /**
90      * This method reset the Thread Network Data.
91      *
92      */
93     void Reset(void);
94 
95     /**
96      * This method starts the Leader services.
97      *
98      */
99     void Start(void);
100 
101     /**
102      * This method stops the Leader services.
103      *
104      */
105     void Stop(void);
106 
107     /**
108      * This method increments the Thread Network Data version.
109      *
110      */
111     void IncrementVersion(void);
112 
113     /**
114      * This method increments both the Thread Network Data version and stable version.
115      *
116      */
117     void IncrementVersionAndStableVersion(void);
118 
119     /**
120      * This method returns CONTEXT_ID_RESUSE_DELAY value.
121      *
122      * @returns The CONTEXT_ID_REUSE_DELAY value.
123      *
124      */
GetContextIdReuseDelay(void) const125     uint32_t GetContextIdReuseDelay(void) const { return mContextIdReuseDelay; }
126 
127     /**
128      * This method sets CONTEXT_ID_RESUSE_DELAY value.
129      *
130      * @warning This method should only be used for testing.
131      *
132      * @param[in]  aDelay  The CONTEXT_ID_REUSE_DELAY value.
133      *
134      */
SetContextIdReuseDelay(uint32_t aDelay)135     void SetContextIdReuseDelay(uint32_t aDelay) { mContextIdReuseDelay = aDelay; }
136 
137     /**
138      * This method removes Network Data entries matching with a given RLOC16.
139      *
140      * @param[in]  aRloc16    A RLOC16 value.
141      * @param[in]  aMatchMode A match mode (@sa MatchMode).
142      *
143      */
144     void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode);
145 
146     /**
147      * This method synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data.
148      *
149      * Note that this method should be called only by the Leader once after reset.
150      *
151      */
152     void UpdateContextsAfterReset(void);
153 
154     /**
155      * This method scans network data for given Service ID and returns pointer to the respective TLV, if present.
156      *
157      * @param aServiceId Service ID to look for.
158      * @return Pointer to the Service TLV for given Service ID, or nullptr if not present.
159      *
160      */
161     const ServiceTlv *FindServiceById(uint8_t aServiceId) const;
162 
163     /**
164      * This method sends SVR_DATA.ntf message for any stale child entries that exist in the network data.
165      *
166      * @param[in]  aHandler  A function pointer that is called when the transaction ends.
167      * @param[in]  aContext  A pointer to arbitrary context information.
168      *
169      * @retval kErrorNone      A stale child entry was found and successfully enqueued a SVR_DATA.ntf message.
170      * @retval kErrorNoBufs    A stale child entry was found, but insufficient message buffers were available.
171      * @retval kErrorNotFound  No stale child entries were found.
172      *
173      */
174     Error RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext);
175 
176 private:
177     class ChangedFlags
178     {
179     public:
ChangedFlags(void)180         ChangedFlags(void)
181             : mChanged(false)
182             , mStableChanged(false)
183         {
184         }
185 
Update(const NetworkDataTlv & aTlv)186         void Update(const NetworkDataTlv &aTlv)
187         {
188             mChanged       = true;
189             mStableChanged = (mStableChanged || aTlv.IsStable());
190         }
191 
DidChange(void) const192         bool DidChange(void) const { return mChanged; }
DidStableChange(void) const193         bool DidStableChange(void) const { return mStableChanged; }
194 
195     private:
196         bool mChanged;       // Any (stable or not) network data change (add/remove).
197         bool mStableChanged; // Stable network data change (add/remove).
198     };
199 
200     enum UpdateStatus : uint8_t
201     {
202         kTlvRemoved, // TLV contained no sub TLVs and therefore is removed.
203         kTlvUpdated, // TLV stable flag is updated based on its sub TLVs.
204     };
205 
206     static void HandleServerData(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
207     void        HandleServerData(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
208 
209     static void HandleTimer(Timer &aTimer);
210     void        HandleTimer(void);
211 
212     void RegisterNetworkData(uint16_t aRloc16, const uint8_t *aTlvs, uint8_t aTlvsLength);
213 
214     Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags);
215     Error AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
216     Error AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
217     Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags);
218     Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags);
219 
220     Error AllocateServiceId(uint8_t &aServiceId) const;
221 
222     Error AllocateContextId(uint8_t &aContextId);
223     void  FreeContextId(uint8_t aContextId);
224     void  StartContextReuseTimer(uint8_t aContextId);
225     void  StopContextReuseTimer(uint8_t aContextId);
226 
227     void RemoveContext(uint8_t aContextId);
228     void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId);
229 
230     void RemoveCommissioningData(void);
231 
232     void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags);
233     void RemoveRloc(uint16_t       aRloc16,
234                     MatchMode      aMatchMode,
235                     const uint8_t *aExcludeTlvs,
236                     uint8_t        aExcludeTlvsLength,
237                     ChangedFlags & aChangedFlags);
238     void RemoveRlocInPrefix(PrefixTlv &      aPrefix,
239                             uint16_t         aRloc16,
240                             MatchMode        aMatchMode,
241                             const PrefixTlv *aExcludePrefix,
242                             ChangedFlags &   aChangedFlags);
243     void RemoveRlocInService(ServiceTlv &      aService,
244                              uint16_t          aRloc16,
245                              MatchMode         aMatchMode,
246                              const ServiceTlv *aExcludeService,
247                              ChangedFlags &    aChangedFlags);
248     void RemoveRlocInHasRoute(PrefixTlv &      aPrefix,
249                               HasRouteTlv &    aHasRoute,
250                               uint16_t         aRloc16,
251                               MatchMode        aMatchMode,
252                               const PrefixTlv *aExcludePrefix,
253                               ChangedFlags &   aChangedFlags);
254     void RemoveRlocInBorderRouter(PrefixTlv &      aPrefix,
255                                   BorderRouterTlv &aBorderRouter,
256                                   uint16_t         aRloc16,
257                                   MatchMode        aMatchMode,
258                                   const PrefixTlv *aExcludePrefix,
259                                   ChangedFlags &   aChangedFlags);
260 
261     static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode);
262 
263     static Error Validate(const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aRloc16);
264     static Error ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16);
265     static Error ValidateService(const ServiceTlv &aService, uint16_t aRloc16);
266 
267     static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const HasRouteEntry &aEntry);
268     static bool ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry);
269     static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry);
270     static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry);
271     static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer);
272 
273     UpdateStatus UpdatePrefix(PrefixTlv &aPrefix);
274     UpdateStatus UpdateService(ServiceTlv &aService);
275     UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs);
276 
277     static void HandleCommissioningSet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
278     void        HandleCommissioningSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
279 
280     static void HandleCommissioningGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
281     void        HandleCommissioningGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
282 
283     void SendCommissioningGetResponse(const Coap::Message &   aRequest,
284                                       uint16_t                aLength,
285                                       const Ip6::MessageInfo &aMessageInfo);
286     void SendCommissioningSetResponse(const Coap::Message &    aRequest,
287                                       const Ip6::MessageInfo & aMessageInfo,
288                                       MeshCoP::StateTlv::State aState);
289     void IncrementVersions(bool aIncludeStable);
290     void IncrementVersions(const ChangedFlags &aFlags);
291 
292     static constexpr uint8_t  kMinContextId        = 1;            // Minimum Context ID (0 is used for Mesh Local)
293     static constexpr uint8_t  kNumContextIds       = 15;           // Maximum Context ID
294     static constexpr uint32_t kContextIdReuseDelay = 48 * 60 * 60; // in seconds
295     static constexpr uint32_t kStateUpdatePeriod   = 60 * 1000;    // State update period in milliseconds
296 
297     uint16_t   mContextUsed;
298     TimeMilli  mContextLastUsed[kNumContextIds];
299     uint32_t   mContextIdReuseDelay;
300     TimerMilli mTimer;
301 
302     Coap::Resource mServerData;
303 
304     Coap::Resource mCommissioningDataGet;
305     Coap::Resource mCommissioningDataSet;
306 };
307 
308 /**
309  * @}
310  */
311 
312 } // namespace NetworkData
313 } // namespace ot
314 
315 #endif // OPENTHREAD_FTD
316 
317 #endif // NETWORK_DATA_LEADER_FTD_HPP_
318