1 /*
2  *  Copyright (c) 2016-2017, 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 implements the OpenThread Thread API (FTD only).
32  */
33 
34 #include "openthread-core-config.h"
35 
36 #if OPENTHREAD_FTD
37 
38 #include <openthread/thread_ftd.h>
39 
40 #include "backbone_router/bbr_manager.hpp"
41 #include "common/instance.hpp"
42 #include "common/locator_getters.hpp"
43 #include "thread/mle_types.hpp"
44 #include "thread/topology.hpp"
45 
46 using namespace ot;
47 
otThreadGetMaxAllowedChildren(otInstance * aInstance)48 uint16_t otThreadGetMaxAllowedChildren(otInstance *aInstance)
49 {
50     Instance &instance = *static_cast<Instance *>(aInstance);
51 
52     return instance.Get<ChildTable>().GetMaxChildrenAllowed();
53 }
54 
otThreadSetMaxAllowedChildren(otInstance * aInstance,uint16_t aMaxChildren)55 otError otThreadSetMaxAllowedChildren(otInstance *aInstance, uint16_t aMaxChildren)
56 {
57     Instance &instance = *static_cast<Instance *>(aInstance);
58 
59     return instance.Get<ChildTable>().SetMaxChildrenAllowed(aMaxChildren);
60 }
61 
otThreadGetMaxChildIpAddresses(otInstance * aInstance)62 uint8_t otThreadGetMaxChildIpAddresses(otInstance *aInstance)
63 {
64     Instance &instance = *static_cast<Instance *>(aInstance);
65 
66     return instance.Get<Mle::MleRouter>().GetMaxChildIpAddresses();
67 }
68 
69 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otThreadSetMaxChildIpAddresses(otInstance * aInstance,uint8_t aMaxIpAddresses)70 otError otThreadSetMaxChildIpAddresses(otInstance *aInstance, uint8_t aMaxIpAddresses)
71 {
72     Instance &instance = *static_cast<Instance *>(aInstance);
73 
74     return instance.Get<Mle::MleRouter>().SetMaxChildIpAddresses(aMaxIpAddresses);
75 }
76 #endif
77 
otThreadIsRouterEligible(otInstance * aInstance)78 bool otThreadIsRouterEligible(otInstance *aInstance)
79 {
80     Instance &instance = *static_cast<Instance *>(aInstance);
81 
82     return instance.Get<Mle::MleRouter>().IsRouterEligible();
83 }
84 
otThreadSetRouterEligible(otInstance * aInstance,bool aEligible)85 otError otThreadSetRouterEligible(otInstance *aInstance, bool aEligible)
86 {
87     Instance &instance = *static_cast<Instance *>(aInstance);
88 
89     return instance.Get<Mle::MleRouter>().SetRouterEligible(aEligible);
90 }
91 
otThreadSetPreferredRouterId(otInstance * aInstance,uint8_t aRouterId)92 otError otThreadSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId)
93 {
94     Instance &instance = *static_cast<Instance *>(aInstance);
95 
96     return instance.Get<Mle::MleRouter>().SetPreferredRouterId(aRouterId);
97 }
98 
otThreadGetLocalLeaderWeight(otInstance * aInstance)99 uint8_t otThreadGetLocalLeaderWeight(otInstance *aInstance)
100 {
101     Instance &instance = *static_cast<Instance *>(aInstance);
102 
103     return instance.Get<Mle::MleRouter>().GetLeaderWeight();
104 }
105 
otThreadSetLocalLeaderWeight(otInstance * aInstance,uint8_t aWeight)106 void otThreadSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight)
107 {
108     Instance &instance = *static_cast<Instance *>(aInstance);
109 
110     instance.Get<Mle::MleRouter>().SetLeaderWeight(aWeight);
111 }
112 
113 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otThreadGetPreferredLeaderPartitionId(otInstance * aInstance)114 uint32_t otThreadGetPreferredLeaderPartitionId(otInstance *aInstance)
115 {
116     Instance &instance = *static_cast<Instance *>(aInstance);
117 
118     return instance.Get<Mle::MleRouter>().GetPreferredLeaderPartitionId();
119 }
120 
otThreadSetPreferredLeaderPartitionId(otInstance * aInstance,uint32_t aPartitionId)121 void otThreadSetPreferredLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId)
122 {
123     Instance &instance = *static_cast<Instance *>(aInstance);
124 
125     instance.Get<Mle::MleRouter>().SetPreferredLeaderPartitionId(aPartitionId);
126 }
127 #endif
128 
otThreadGetJoinerUdpPort(otInstance * aInstance)129 uint16_t otThreadGetJoinerUdpPort(otInstance *aInstance)
130 {
131     Instance &instance = *static_cast<Instance *>(aInstance);
132 
133     return instance.Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort();
134 }
135 
otThreadSetJoinerUdpPort(otInstance * aInstance,uint16_t aJoinerUdpPort)136 otError otThreadSetJoinerUdpPort(otInstance *aInstance, uint16_t aJoinerUdpPort)
137 {
138     Instance &instance = *static_cast<Instance *>(aInstance);
139 
140     instance.Get<MeshCoP::JoinerRouter>().SetJoinerUdpPort(aJoinerUdpPort);
141 
142     return kErrorNone;
143 }
144 
otThreadGetContextIdReuseDelay(otInstance * aInstance)145 uint32_t otThreadGetContextIdReuseDelay(otInstance *aInstance)
146 {
147     Instance &instance = *static_cast<Instance *>(aInstance);
148 
149     return instance.Get<NetworkData::Leader>().GetContextIdReuseDelay();
150 }
151 
otThreadSetContextIdReuseDelay(otInstance * aInstance,uint32_t aDelay)152 void otThreadSetContextIdReuseDelay(otInstance *aInstance, uint32_t aDelay)
153 {
154     Instance &instance = *static_cast<Instance *>(aInstance);
155 
156     instance.Get<NetworkData::Leader>().SetContextIdReuseDelay(aDelay);
157 }
158 
otThreadGetNetworkIdTimeout(otInstance * aInstance)159 uint8_t otThreadGetNetworkIdTimeout(otInstance *aInstance)
160 {
161     Instance &instance = *static_cast<Instance *>(aInstance);
162 
163     return instance.Get<Mle::MleRouter>().GetNetworkIdTimeout();
164 }
165 
otThreadSetNetworkIdTimeout(otInstance * aInstance,uint8_t aTimeout)166 void otThreadSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout)
167 {
168     Instance &instance = *static_cast<Instance *>(aInstance);
169 
170     instance.Get<Mle::MleRouter>().SetNetworkIdTimeout(aTimeout);
171 }
172 
otThreadGetRouterUpgradeThreshold(otInstance * aInstance)173 uint8_t otThreadGetRouterUpgradeThreshold(otInstance *aInstance)
174 {
175     Instance &instance = *static_cast<Instance *>(aInstance);
176 
177     return instance.Get<Mle::MleRouter>().GetRouterUpgradeThreshold();
178 }
179 
otThreadSetRouterUpgradeThreshold(otInstance * aInstance,uint8_t aThreshold)180 void otThreadSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold)
181 {
182     Instance &instance = *static_cast<Instance *>(aInstance);
183 
184     instance.Get<Mle::MleRouter>().SetRouterUpgradeThreshold(aThreshold);
185 }
186 
otThreadReleaseRouterId(otInstance * aInstance,uint8_t aRouterId)187 otError otThreadReleaseRouterId(otInstance *aInstance, uint8_t aRouterId)
188 {
189     Error     error    = kErrorNone;
190     Instance &instance = *static_cast<Instance *>(aInstance);
191 
192     VerifyOrExit(aRouterId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
193 
194     error = instance.Get<RouterTable>().Release(aRouterId);
195 
196 exit:
197     return error;
198 }
199 
otThreadBecomeRouter(otInstance * aInstance)200 otError otThreadBecomeRouter(otInstance *aInstance)
201 {
202     Error     error    = kErrorInvalidState;
203     Instance &instance = *static_cast<Instance *>(aInstance);
204 
205     switch (instance.Get<Mle::MleRouter>().GetRole())
206     {
207     case Mle::kRoleDisabled:
208     case Mle::kRoleDetached:
209         break;
210 
211     case Mle::kRoleChild:
212         error = instance.Get<Mle::MleRouter>().BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest);
213         break;
214 
215     case Mle::kRoleRouter:
216     case Mle::kRoleLeader:
217         error = kErrorNone;
218         break;
219     }
220 
221     return error;
222 }
223 
otThreadBecomeLeader(otInstance * aInstance)224 otError otThreadBecomeLeader(otInstance *aInstance)
225 {
226     Instance &instance = *static_cast<Instance *>(aInstance);
227 
228     return instance.Get<Mle::MleRouter>().BecomeLeader();
229 }
230 
otThreadGetRouterDowngradeThreshold(otInstance * aInstance)231 uint8_t otThreadGetRouterDowngradeThreshold(otInstance *aInstance)
232 {
233     Instance &instance = *static_cast<Instance *>(aInstance);
234 
235     return instance.Get<Mle::MleRouter>().GetRouterDowngradeThreshold();
236 }
237 
otThreadSetRouterDowngradeThreshold(otInstance * aInstance,uint8_t aThreshold)238 void otThreadSetRouterDowngradeThreshold(otInstance *aInstance, uint8_t aThreshold)
239 {
240     Instance &instance = *static_cast<Instance *>(aInstance);
241 
242     instance.Get<Mle::MleRouter>().SetRouterDowngradeThreshold(aThreshold);
243 }
244 
otThreadGetRouterSelectionJitter(otInstance * aInstance)245 uint8_t otThreadGetRouterSelectionJitter(otInstance *aInstance)
246 {
247     Instance &instance = *static_cast<Instance *>(aInstance);
248 
249     return instance.Get<Mle::MleRouter>().GetRouterSelectionJitter();
250 }
251 
otThreadSetRouterSelectionJitter(otInstance * aInstance,uint8_t aRouterJitter)252 void otThreadSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter)
253 {
254     Instance &instance = *static_cast<Instance *>(aInstance);
255 
256     IgnoreError(instance.Get<Mle::MleRouter>().SetRouterSelectionJitter(aRouterJitter));
257 }
258 
otThreadGetChildInfoById(otInstance * aInstance,uint16_t aChildId,otChildInfo * aChildInfo)259 otError otThreadGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo)
260 {
261     Instance &instance = *static_cast<Instance *>(aInstance);
262 
263     OT_ASSERT(aChildInfo != nullptr);
264 
265     return instance.Get<ChildTable>().GetChildInfoById(aChildId, *static_cast<Child::Info *>(aChildInfo));
266 }
267 
otThreadGetChildInfoByIndex(otInstance * aInstance,uint16_t aChildIndex,otChildInfo * aChildInfo)268 otError otThreadGetChildInfoByIndex(otInstance *aInstance, uint16_t aChildIndex, otChildInfo *aChildInfo)
269 {
270     Instance &instance = *static_cast<Instance *>(aInstance);
271 
272     OT_ASSERT(aChildInfo != nullptr);
273 
274     return instance.Get<ChildTable>().GetChildInfoByIndex(aChildIndex, *static_cast<Child::Info *>(aChildInfo));
275 }
276 
otThreadGetChildNextIp6Address(otInstance * aInstance,uint16_t aChildIndex,otChildIp6AddressIterator * aIterator,otIp6Address * aAddress)277 otError otThreadGetChildNextIp6Address(otInstance *               aInstance,
278                                        uint16_t                   aChildIndex,
279                                        otChildIp6AddressIterator *aIterator,
280                                        otIp6Address *             aAddress)
281 {
282     Error        error    = kErrorNone;
283     Instance &   instance = *static_cast<Instance *>(aInstance);
284     const Child *child;
285 
286     OT_ASSERT(aIterator != nullptr && aAddress != nullptr);
287 
288     child = instance.Get<ChildTable>().GetChildAtIndex(aChildIndex);
289     VerifyOrExit(child != nullptr, error = kErrorInvalidArgs);
290     VerifyOrExit(child->IsStateValidOrRestoring(), error = kErrorInvalidArgs);
291 
292     {
293         Child::AddressIterator iter(*child, *aIterator);
294 
295         VerifyOrExit(!iter.IsDone(), error = kErrorNotFound);
296         *aAddress = *iter.GetAddress();
297 
298         iter++;
299         *aIterator = iter.GetAsIndex();
300     }
301 
302 exit:
303     return error;
304 }
305 
otThreadGetRouterIdSequence(otInstance * aInstance)306 uint8_t otThreadGetRouterIdSequence(otInstance *aInstance)
307 {
308     Instance &instance = *static_cast<Instance *>(aInstance);
309 
310     return instance.Get<RouterTable>().GetRouterIdSequence();
311 }
312 
otThreadGetMaxRouterId(otInstance * aInstance)313 uint8_t otThreadGetMaxRouterId(otInstance *aInstance)
314 {
315     OT_UNUSED_VARIABLE(aInstance);
316     return Mle::kMaxRouterId;
317 }
318 
otThreadGetRouterInfo(otInstance * aInstance,uint16_t aRouterId,otRouterInfo * aRouterInfo)319 otError otThreadGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterInfo *aRouterInfo)
320 {
321     Instance &instance = *static_cast<Instance *>(aInstance);
322 
323     OT_ASSERT(aRouterInfo != nullptr);
324 
325     return instance.Get<RouterTable>().GetRouterInfo(aRouterId, *static_cast<Router::Info *>(aRouterInfo));
326 }
327 
otThreadGetNextCacheEntry(otInstance * aInstance,otCacheEntryInfo * aEntryInfo,otCacheEntryIterator * aIterator)328 otError otThreadGetNextCacheEntry(otInstance *aInstance, otCacheEntryInfo *aEntryInfo, otCacheEntryIterator *aIterator)
329 {
330     Instance &instance = *static_cast<Instance *>(aInstance);
331 
332     OT_ASSERT((aIterator != nullptr) && (aEntryInfo != nullptr));
333 
334     return instance.Get<AddressResolver>().GetNextCacheEntry(*aEntryInfo, *aIterator);
335 }
336 
337 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
otThreadSetSteeringData(otInstance * aInstance,const otExtAddress * aExtAddress)338 void otThreadSetSteeringData(otInstance *aInstance, const otExtAddress *aExtAddress)
339 {
340     Instance &instance = *static_cast<Instance *>(aInstance);
341 
342     instance.Get<Mle::MleRouter>().SetSteeringData(static_cast<const Mac::ExtAddress *>(aExtAddress));
343 }
344 #endif
345 
otThreadGetPskc(otInstance * aInstance)346 const otPskc *otThreadGetPskc(otInstance *aInstance)
347 {
348     Instance &instance = *static_cast<Instance *>(aInstance);
349 
350     return &instance.Get<KeyManager>().GetPskc();
351 }
352 
otThreadSetPskc(otInstance * aInstance,const otPskc * aPskc)353 otError otThreadSetPskc(otInstance *aInstance, const otPskc *aPskc)
354 {
355     Error     error    = kErrorNone;
356     Instance &instance = *static_cast<Instance *>(aInstance);
357 
358     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
359 
360     instance.Get<KeyManager>().SetPskc(*static_cast<const Pskc *>(aPskc));
361     instance.Get<MeshCoP::ActiveDataset>().Clear();
362     instance.Get<MeshCoP::PendingDataset>().Clear();
363 
364 exit:
365     return error;
366 }
367 
otThreadGetParentPriority(otInstance * aInstance)368 int8_t otThreadGetParentPriority(otInstance *aInstance)
369 {
370     Instance &instance = *static_cast<Instance *>(aInstance);
371 
372     return instance.Get<Mle::MleRouter>().GetAssignParentPriority();
373 }
374 
otThreadSetParentPriority(otInstance * aInstance,int8_t aParentPriority)375 otError otThreadSetParentPriority(otInstance *aInstance, int8_t aParentPriority)
376 {
377     Instance &instance = *static_cast<Instance *>(aInstance);
378 
379     return instance.Get<Mle::MleRouter>().SetAssignParentPriority(aParentPriority);
380 }
381 
otThreadRegisterNeighborTableCallback(otInstance * aInstance,otNeighborTableCallback aCallback)382 void otThreadRegisterNeighborTableCallback(otInstance *aInstance, otNeighborTableCallback aCallback)
383 {
384     Instance &instance = *static_cast<Instance *>(aInstance);
385 
386     instance.Get<NeighborTable>().RegisterCallback(aCallback);
387 }
388 
otThreadSetDiscoveryRequestCallback(otInstance * aInstance,otThreadDiscoveryRequestCallback aCallback,void * aContext)389 void otThreadSetDiscoveryRequestCallback(otInstance *                     aInstance,
390                                          otThreadDiscoveryRequestCallback aCallback,
391                                          void *                           aContext)
392 {
393     Instance &instance = *static_cast<Instance *>(aInstance);
394 
395     instance.Get<Mle::MleRouter>().SetDiscoveryRequestCallback(aCallback, aContext);
396 }
397 
398 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otThreadSendAddressNotification(otInstance * aInstance,otIp6Address * aDestination,otIp6Address * aTarget,otIp6InterfaceIdentifier * aMlIid)399 void otThreadSendAddressNotification(otInstance *              aInstance,
400                                      otIp6Address *            aDestination,
401                                      otIp6Address *            aTarget,
402                                      otIp6InterfaceIdentifier *aMlIid)
403 {
404     Instance &instance = *static_cast<Instance *>(aInstance);
405 
406     instance.Get<AddressResolver>().SendAddressQueryResponse(static_cast<Ip6::Address &>(*aTarget),
407                                                              static_cast<Ip6::InterfaceIdentifier &>(*aMlIid), nullptr,
408                                                              static_cast<Ip6::Address &>(*aDestination));
409 }
410 
411 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
otThreadSendProactiveBackboneNotification(otInstance * aInstance,otIp6Address * aTarget,otIp6InterfaceIdentifier * aMlIid,uint32_t aTimeSinceLastTransaction)412 otError otThreadSendProactiveBackboneNotification(otInstance *              aInstance,
413                                                   otIp6Address *            aTarget,
414                                                   otIp6InterfaceIdentifier *aMlIid,
415                                                   uint32_t                  aTimeSinceLastTransaction)
416 {
417     Instance &instance = *static_cast<Instance *>(aInstance);
418 
419     return instance.Get<BackboneRouter::Manager>().SendProactiveBackboneNotification(
420         static_cast<Ip6::Address &>(*aTarget), static_cast<Ip6::InterfaceIdentifier &>(*aMlIid),
421         aTimeSinceLastTransaction);
422 }
423 #endif
424 #endif
425 
426 #endif // OPENTHREAD_FTD
427