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