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