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 implements the OpenThread Thread API (for both FTD and MTD).
32  */
33 
34 #include "openthread-core-config.h"
35 
36 #if OPENTHREAD_FTD || OPENTHREAD_MTD
37 
38 #include <openthread/thread.h>
39 
40 #include "common/debug.hpp"
41 #include "common/instance.hpp"
42 #include "common/locator_getters.hpp"
43 #include "common/settings.hpp"
44 
45 using namespace ot;
46 
otThreadGetChildTimeout(otInstance * aInstance)47 uint32_t otThreadGetChildTimeout(otInstance *aInstance)
48 {
49     Instance &instance = *static_cast<Instance *>(aInstance);
50 
51     return instance.Get<Mle::MleRouter>().GetTimeout();
52 }
53 
otThreadSetChildTimeout(otInstance * aInstance,uint32_t aTimeout)54 void otThreadSetChildTimeout(otInstance *aInstance, uint32_t aTimeout)
55 {
56     Instance &instance = *static_cast<Instance *>(aInstance);
57 
58     instance.Get<Mle::MleRouter>().SetTimeout(aTimeout);
59 }
60 
otThreadGetExtendedPanId(otInstance * aInstance)61 const otExtendedPanId *otThreadGetExtendedPanId(otInstance *aInstance)
62 {
63     Instance &instance = *static_cast<Instance *>(aInstance);
64 
65     return &instance.Get<Mac::Mac>().GetExtendedPanId();
66 }
67 
otThreadSetExtendedPanId(otInstance * aInstance,const otExtendedPanId * aExtendedPanId)68 otError otThreadSetExtendedPanId(otInstance *aInstance, const otExtendedPanId *aExtendedPanId)
69 {
70     Error                     error    = kErrorNone;
71     Instance &                instance = *static_cast<Instance *>(aInstance);
72     const Mac::ExtendedPanId &extPanId = *static_cast<const Mac::ExtendedPanId *>(aExtendedPanId);
73     Mle::MeshLocalPrefix      prefix;
74 
75     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
76 
77     instance.Get<Mac::Mac>().SetExtendedPanId(extPanId);
78 
79     prefix.SetFromExtendedPanId(extPanId);
80     instance.Get<Mle::MleRouter>().SetMeshLocalPrefix(prefix);
81 
82     instance.Get<MeshCoP::ActiveDataset>().Clear();
83     instance.Get<MeshCoP::PendingDataset>().Clear();
84 
85 exit:
86     return error;
87 }
88 
otThreadGetLeaderRloc(otInstance * aInstance,otIp6Address * aLeaderRloc)89 otError otThreadGetLeaderRloc(otInstance *aInstance, otIp6Address *aLeaderRloc)
90 {
91     Instance &instance = *static_cast<Instance *>(aInstance);
92 
93     OT_ASSERT(aLeaderRloc != nullptr);
94 
95     return instance.Get<Mle::MleRouter>().GetLeaderAddress(*static_cast<Ip6::Address *>(aLeaderRloc));
96 }
97 
otThreadGetLinkMode(otInstance * aInstance)98 otLinkModeConfig otThreadGetLinkMode(otInstance *aInstance)
99 {
100     otLinkModeConfig config;
101     Instance &       instance = *static_cast<Instance *>(aInstance);
102 
103     instance.Get<Mle::MleRouter>().GetDeviceMode().Get(config);
104 
105     return config;
106 }
107 
otThreadSetLinkMode(otInstance * aInstance,otLinkModeConfig aConfig)108 otError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig)
109 {
110     Instance &instance = *static_cast<Instance *>(aInstance);
111 
112     return instance.Get<Mle::MleRouter>().SetDeviceMode(Mle::DeviceMode(aConfig));
113 }
114 
otThreadGetNetworkKey(otInstance * aInstance)115 const otNetworkKey *otThreadGetNetworkKey(otInstance *aInstance)
116 {
117     Instance &instance = *static_cast<Instance *>(aInstance);
118 
119     return &instance.Get<KeyManager>().GetNetworkKey();
120 }
121 
otThreadSetNetworkKey(otInstance * aInstance,const otNetworkKey * aKey)122 otError otThreadSetNetworkKey(otInstance *aInstance, const otNetworkKey *aKey)
123 {
124     Error     error    = kErrorNone;
125     Instance &instance = *static_cast<Instance *>(aInstance);
126 
127     OT_ASSERT(aKey != nullptr);
128 
129     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
130 
131     error = instance.Get<KeyManager>().SetNetworkKey(*static_cast<const NetworkKey *>(aKey));
132     instance.Get<MeshCoP::ActiveDataset>().Clear();
133     instance.Get<MeshCoP::PendingDataset>().Clear();
134 
135 exit:
136     return error;
137 }
138 
otThreadGetRloc(otInstance * aInstance)139 const otIp6Address *otThreadGetRloc(otInstance *aInstance)
140 {
141     Instance &instance = *static_cast<Instance *>(aInstance);
142 
143     return &instance.Get<Mle::MleRouter>().GetMeshLocal16();
144 }
145 
otThreadGetMeshLocalEid(otInstance * aInstance)146 const otIp6Address *otThreadGetMeshLocalEid(otInstance *aInstance)
147 {
148     Instance &instance = *static_cast<Instance *>(aInstance);
149 
150     return &instance.Get<Mle::MleRouter>().GetMeshLocal64();
151 }
152 
otThreadGetMeshLocalPrefix(otInstance * aInstance)153 const otMeshLocalPrefix *otThreadGetMeshLocalPrefix(otInstance *aInstance)
154 {
155     Instance &instance = *static_cast<Instance *>(aInstance);
156 
157     return &instance.Get<Mle::MleRouter>().GetMeshLocalPrefix();
158 }
159 
otThreadSetMeshLocalPrefix(otInstance * aInstance,const otMeshLocalPrefix * aMeshLocalPrefix)160 otError otThreadSetMeshLocalPrefix(otInstance *aInstance, const otMeshLocalPrefix *aMeshLocalPrefix)
161 {
162     Error     error    = kErrorNone;
163     Instance &instance = *static_cast<Instance *>(aInstance);
164 
165     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
166 
167     instance.Get<Mle::MleRouter>().SetMeshLocalPrefix(*static_cast<const Mle::MeshLocalPrefix *>(aMeshLocalPrefix));
168     instance.Get<MeshCoP::ActiveDataset>().Clear();
169     instance.Get<MeshCoP::PendingDataset>().Clear();
170 
171 exit:
172     return error;
173 }
174 
otThreadGetLinkLocalIp6Address(otInstance * aInstance)175 const otIp6Address *otThreadGetLinkLocalIp6Address(otInstance *aInstance)
176 {
177     Instance &instance = *static_cast<Instance *>(aInstance);
178 
179     return &instance.Get<Mle::MleRouter>().GetLinkLocalAddress();
180 }
181 
otThreadGetLinkLocalAllThreadNodesMulticastAddress(otInstance * aInstance)182 const otIp6Address *otThreadGetLinkLocalAllThreadNodesMulticastAddress(otInstance *aInstance)
183 {
184     Instance &instance = *static_cast<Instance *>(aInstance);
185 
186     return &instance.Get<Mle::MleRouter>().GetLinkLocalAllThreadNodesAddress();
187 }
188 
otThreadGetRealmLocalAllThreadNodesMulticastAddress(otInstance * aInstance)189 const otIp6Address *otThreadGetRealmLocalAllThreadNodesMulticastAddress(otInstance *aInstance)
190 {
191     Instance &instance = *static_cast<Instance *>(aInstance);
192 
193     return &instance.Get<Mle::MleRouter>().GetRealmLocalAllThreadNodesAddress();
194 }
195 
otThreadGetServiceAloc(otInstance * aInstance,uint8_t aServiceId,otIp6Address * aServiceAloc)196 otError otThreadGetServiceAloc(otInstance *aInstance, uint8_t aServiceId, otIp6Address *aServiceAloc)
197 {
198     Instance &instance = *static_cast<Instance *>(aInstance);
199 
200     return instance.Get<Mle::MleRouter>().GetServiceAloc(aServiceId, *static_cast<Ip6::Address *>(aServiceAloc));
201 }
202 
otThreadGetNetworkName(otInstance * aInstance)203 const char *otThreadGetNetworkName(otInstance *aInstance)
204 {
205     Instance &instance = *static_cast<Instance *>(aInstance);
206 
207     return instance.Get<Mac::Mac>().GetNetworkName().GetAsCString();
208 }
209 
otThreadSetNetworkName(otInstance * aInstance,const char * aNetworkName)210 otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName)
211 {
212     Error     error    = kErrorNone;
213     Instance &instance = *static_cast<Instance *>(aInstance);
214 
215     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
216 
217     error = instance.Get<Mac::Mac>().SetNetworkName(aNetworkName);
218     instance.Get<MeshCoP::ActiveDataset>().Clear();
219     instance.Get<MeshCoP::PendingDataset>().Clear();
220 
221 exit:
222     return error;
223 }
224 
225 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
otThreadGetDomainName(otInstance * aInstance)226 const char *otThreadGetDomainName(otInstance *aInstance)
227 {
228     Instance &instance = *static_cast<Instance *>(aInstance);
229 
230     return instance.Get<Mac::Mac>().GetDomainName().GetAsCString();
231 }
232 
otThreadSetDomainName(otInstance * aInstance,const char * aDomainName)233 otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName)
234 {
235     Error     error    = kErrorNone;
236     Instance &instance = *static_cast<Instance *>(aInstance);
237 
238     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
239 
240     error = instance.Get<Mac::Mac>().SetDomainName(aDomainName);
241 
242 exit:
243     return error;
244 }
245 
246 #if OPENTHREAD_CONFIG_DUA_ENABLE
otThreadSetFixedDuaInterfaceIdentifier(otInstance * aInstance,const otIp6InterfaceIdentifier * aIid)247 otError otThreadSetFixedDuaInterfaceIdentifier(otInstance *aInstance, const otIp6InterfaceIdentifier *aIid)
248 {
249     Instance &instance = *static_cast<Instance *>(aInstance);
250     Error     error    = kErrorNone;
251 
252     if (aIid)
253     {
254         error = instance.Get<DuaManager>().SetFixedDuaInterfaceIdentifier(
255             *static_cast<const Ip6::InterfaceIdentifier *>(aIid));
256     }
257     else
258     {
259         instance.Get<DuaManager>().ClearFixedDuaInterfaceIdentifier();
260     }
261 
262     return error;
263 }
264 
otThreadGetFixedDuaInterfaceIdentifier(otInstance * aInstance)265 const otIp6InterfaceIdentifier *otThreadGetFixedDuaInterfaceIdentifier(otInstance *aInstance)
266 {
267     Instance &                      instance = *static_cast<Instance *>(aInstance);
268     const otIp6InterfaceIdentifier *iid      = nullptr;
269 
270     if (instance.Get<DuaManager>().IsFixedDuaInterfaceIdentifierSet())
271     {
272         iid = &instance.Get<DuaManager>().GetFixedDuaInterfaceIdentifier();
273     }
274 
275     return iid;
276 }
277 #endif // OPENTHREAD_CONFIG_DUA_ENABLE
278 
279 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
280 
otThreadGetKeySequenceCounter(otInstance * aInstance)281 uint32_t otThreadGetKeySequenceCounter(otInstance *aInstance)
282 {
283     Instance &instance = *static_cast<Instance *>(aInstance);
284 
285     return instance.Get<KeyManager>().GetCurrentKeySequence();
286 }
287 
otThreadSetKeySequenceCounter(otInstance * aInstance,uint32_t aKeySequenceCounter)288 void otThreadSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter)
289 {
290     Instance &instance = *static_cast<Instance *>(aInstance);
291 
292     instance.Get<KeyManager>().SetCurrentKeySequence(aKeySequenceCounter);
293 }
294 
otThreadGetKeySwitchGuardTime(otInstance * aInstance)295 uint32_t otThreadGetKeySwitchGuardTime(otInstance *aInstance)
296 {
297     Instance &instance = *static_cast<Instance *>(aInstance);
298 
299     return instance.Get<KeyManager>().GetKeySwitchGuardTime();
300 }
301 
otThreadSetKeySwitchGuardTime(otInstance * aInstance,uint32_t aKeySwitchGuardTime)302 void otThreadSetKeySwitchGuardTime(otInstance *aInstance, uint32_t aKeySwitchGuardTime)
303 {
304     Instance &instance = *static_cast<Instance *>(aInstance);
305 
306     instance.Get<KeyManager>().SetKeySwitchGuardTime(aKeySwitchGuardTime);
307 }
308 
otThreadBecomeDetached(otInstance * aInstance)309 otError otThreadBecomeDetached(otInstance *aInstance)
310 {
311     Instance &instance = *static_cast<Instance *>(aInstance);
312 
313     return instance.Get<Mle::MleRouter>().BecomeDetached();
314 }
315 
otThreadBecomeChild(otInstance * aInstance)316 otError otThreadBecomeChild(otInstance *aInstance)
317 {
318     Instance &instance = *static_cast<Instance *>(aInstance);
319 
320     return instance.Get<Mle::MleRouter>().BecomeChild(Mle::kAttachAny);
321 }
322 
otThreadGetNextNeighborInfo(otInstance * aInstance,otNeighborInfoIterator * aIterator,otNeighborInfo * aInfo)323 otError otThreadGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterator *aIterator, otNeighborInfo *aInfo)
324 {
325     Instance &instance = *static_cast<Instance *>(aInstance);
326 
327     OT_ASSERT((aInfo != nullptr) && (aIterator != nullptr));
328 
329     return instance.Get<NeighborTable>().GetNextNeighborInfo(*aIterator, *static_cast<Neighbor::Info *>(aInfo));
330 }
331 
otThreadGetDeviceRole(otInstance * aInstance)332 otDeviceRole otThreadGetDeviceRole(otInstance *aInstance)
333 {
334     Instance &instance = *static_cast<Instance *>(aInstance);
335 
336     return static_cast<otDeviceRole>(instance.Get<Mle::MleRouter>().GetRole());
337 }
338 
otThreadDeviceRoleToString(otDeviceRole aRole)339 const char *otThreadDeviceRoleToString(otDeviceRole aRole)
340 {
341     return Mle::Mle::RoleToString(static_cast<Mle::DeviceRole>(aRole));
342 }
343 
otThreadGetLeaderData(otInstance * aInstance,otLeaderData * aLeaderData)344 otError otThreadGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData)
345 {
346     Instance &instance = *static_cast<Instance *>(aInstance);
347     Error     error    = kErrorNone;
348 
349     OT_ASSERT(aLeaderData != nullptr);
350 
351     VerifyOrExit(instance.Get<Mle::MleRouter>().IsAttached(), error = kErrorDetached);
352     *aLeaderData = instance.Get<Mle::MleRouter>().GetLeaderData();
353 
354 exit:
355     return error;
356 }
357 
otThreadGetLeaderRouterId(otInstance * aInstance)358 uint8_t otThreadGetLeaderRouterId(otInstance *aInstance)
359 {
360     Instance &instance = *static_cast<Instance *>(aInstance);
361 
362     return instance.Get<Mle::MleRouter>().GetLeaderId();
363 }
364 
otThreadGetLeaderWeight(otInstance * aInstance)365 uint8_t otThreadGetLeaderWeight(otInstance *aInstance)
366 {
367     Instance &instance = *static_cast<Instance *>(aInstance);
368 
369     return instance.Get<Mle::MleRouter>().GetLeaderData().GetWeighting();
370 }
371 
otThreadGetPartitionId(otInstance * aInstance)372 uint32_t otThreadGetPartitionId(otInstance *aInstance)
373 {
374     Instance &instance = *static_cast<Instance *>(aInstance);
375 
376     return instance.Get<Mle::MleRouter>().GetLeaderData().GetPartitionId();
377 }
378 
otThreadGetRloc16(otInstance * aInstance)379 uint16_t otThreadGetRloc16(otInstance *aInstance)
380 {
381     Instance &instance = *static_cast<Instance *>(aInstance);
382 
383     return instance.Get<Mle::MleRouter>().GetRloc16();
384 }
385 
otThreadGetParentInfo(otInstance * aInstance,otRouterInfo * aParentInfo)386 otError otThreadGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo)
387 {
388     Instance &instance = *static_cast<Instance *>(aInstance);
389     Error     error    = kErrorNone;
390     Router *  parent;
391 
392     OT_ASSERT(aParentInfo != nullptr);
393 
394     // Reference device needs get the original parent's info even after the node state changed.
395 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
396     VerifyOrExit(instance.Get<Mle::MleRouter>().IsChild(), error = kErrorInvalidState);
397 #endif
398 
399     parent = &instance.Get<Mle::MleRouter>().GetParent();
400 
401     aParentInfo->mExtAddress     = parent->GetExtAddress();
402     aParentInfo->mRloc16         = parent->GetRloc16();
403     aParentInfo->mRouterId       = Mle::Mle::RouterIdFromRloc16(parent->GetRloc16());
404     aParentInfo->mNextHop        = parent->GetNextHop();
405     aParentInfo->mPathCost       = parent->GetCost();
406     aParentInfo->mLinkQualityIn  = parent->GetLinkInfo().GetLinkQuality();
407     aParentInfo->mLinkQualityOut = parent->GetLinkQualityOut();
408     aParentInfo->mAge            = static_cast<uint8_t>(Time::MsecToSec(TimerMilli::GetNow() - parent->GetLastHeard()));
409     aParentInfo->mAllocated      = true;
410     aParentInfo->mLinkEstablished = parent->IsStateValid();
411 
412 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
413 exit:
414 #endif
415     return error;
416 }
417 
otThreadGetParentAverageRssi(otInstance * aInstance,int8_t * aParentRssi)418 otError otThreadGetParentAverageRssi(otInstance *aInstance, int8_t *aParentRssi)
419 {
420     Error     error    = kErrorNone;
421     Instance &instance = *static_cast<Instance *>(aInstance);
422 
423     OT_ASSERT(aParentRssi != nullptr);
424 
425     *aParentRssi = instance.Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetAverageRss();
426 
427     VerifyOrExit(*aParentRssi != OT_RADIO_RSSI_INVALID, error = kErrorFailed);
428 
429 exit:
430     return error;
431 }
432 
otThreadGetParentLastRssi(otInstance * aInstance,int8_t * aLastRssi)433 otError otThreadGetParentLastRssi(otInstance *aInstance, int8_t *aLastRssi)
434 {
435     Error     error    = kErrorNone;
436     Instance &instance = *static_cast<Instance *>(aInstance);
437 
438     OT_ASSERT(aLastRssi != nullptr);
439 
440     *aLastRssi = instance.Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetLastRss();
441 
442     VerifyOrExit(*aLastRssi != OT_RADIO_RSSI_INVALID, error = kErrorFailed);
443 
444 exit:
445     return error;
446 }
447 
otThreadSetEnabled(otInstance * aInstance,bool aEnabled)448 otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled)
449 {
450     Error     error    = kErrorNone;
451     Instance &instance = *static_cast<Instance *>(aInstance);
452 
453     if (aEnabled)
454     {
455         error = instance.Get<Mle::MleRouter>().Start(/* aAnnounceAttach */ false);
456     }
457     else
458     {
459         instance.Get<Mle::MleRouter>().Stop(true);
460     }
461 
462     return error;
463 }
464 
otThreadGetVersion(void)465 uint16_t otThreadGetVersion(void)
466 {
467     return OPENTHREAD_CONFIG_THREAD_VERSION;
468 }
469 
otThreadIsSingleton(otInstance * aInstance)470 bool otThreadIsSingleton(otInstance *aInstance)
471 {
472     Instance &instance = *static_cast<Instance *>(aInstance);
473 
474     return instance.Get<Mle::MleRouter>().IsSingleton();
475 }
476 
otThreadDiscover(otInstance * aInstance,uint32_t aScanChannels,uint16_t aPanId,bool aJoiner,bool aEnableEui64Filtering,otHandleActiveScanResult aCallback,void * aCallbackContext)477 otError otThreadDiscover(otInstance *             aInstance,
478                          uint32_t                 aScanChannels,
479                          uint16_t                 aPanId,
480                          bool                     aJoiner,
481                          bool                     aEnableEui64Filtering,
482                          otHandleActiveScanResult aCallback,
483                          void *                   aCallbackContext)
484 {
485     Instance &instance = *static_cast<Instance *>(aInstance);
486 
487     return instance.Get<Mle::DiscoverScanner>().Discover(
488         static_cast<Mac::ChannelMask>(aScanChannels), aPanId, aJoiner, aEnableEui64Filtering,
489         /* aFilterIndexes (use hash of factory EUI64) */ nullptr, aCallback, aCallbackContext);
490 }
491 
otThreadSetJoinerAdvertisement(otInstance * aInstance,uint32_t aOui,const uint8_t * aAdvData,uint8_t aAdvDataLength)492 otError otThreadSetJoinerAdvertisement(otInstance *   aInstance,
493                                        uint32_t       aOui,
494                                        const uint8_t *aAdvData,
495                                        uint8_t        aAdvDataLength)
496 {
497     Instance &instance = *static_cast<Instance *>(aInstance);
498 
499     return instance.Get<Mle::DiscoverScanner>().SetJoinerAdvertisement(aOui, aAdvData, aAdvDataLength);
500 }
501 
otThreadIsDiscoverInProgress(otInstance * aInstance)502 bool otThreadIsDiscoverInProgress(otInstance *aInstance)
503 {
504     Instance &instance = *static_cast<Instance *>(aInstance);
505 
506     return instance.Get<Mle::DiscoverScanner>().IsInProgress();
507 }
508 
otThreadGetIp6Counters(otInstance * aInstance)509 const otIpCounters *otThreadGetIp6Counters(otInstance *aInstance)
510 {
511     Instance &instance = *static_cast<Instance *>(aInstance);
512 
513     return &instance.Get<MeshForwarder>().GetCounters();
514 }
515 
otThreadResetIp6Counters(otInstance * aInstance)516 void otThreadResetIp6Counters(otInstance *aInstance)
517 {
518     Instance &instance = *static_cast<Instance *>(aInstance);
519 
520     instance.Get<MeshForwarder>().ResetCounters();
521 }
522 
otThreadGetMleCounters(otInstance * aInstance)523 const otMleCounters *otThreadGetMleCounters(otInstance *aInstance)
524 {
525     Instance &instance = *static_cast<Instance *>(aInstance);
526 
527     return &instance.Get<Mle::MleRouter>().GetCounters();
528 }
529 
otThreadResetMleCounters(otInstance * aInstance)530 void otThreadResetMleCounters(otInstance *aInstance)
531 {
532     Instance &instance = *static_cast<Instance *>(aInstance);
533 
534     instance.Get<Mle::MleRouter>().ResetCounters();
535 }
536 
otThreadRegisterParentResponseCallback(otInstance * aInstance,otThreadParentResponseCallback aCallback,void * aContext)537 void otThreadRegisterParentResponseCallback(otInstance *                   aInstance,
538                                             otThreadParentResponseCallback aCallback,
539                                             void *                         aContext)
540 {
541     Instance &instance = *static_cast<Instance *>(aInstance);
542 
543     instance.Get<Mle::MleRouter>().RegisterParentResponseStatsCallback(aCallback, aContext);
544 }
545 
546 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
547