1 /*
2 * Copyright (c) 2023, 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 #define OTBR_LOG_TAG "BINDER"
30
31 #include "android/otdaemon_server.hpp"
32
33 #include <net/if.h>
34 #include <string.h>
35
36 #include <android-base/file.h>
37 #include <android-base/stringprintf.h>
38 #include <android/binder_manager.h>
39 #include <android/binder_process.h>
40 #include <openthread/border_router.h>
41 #include <openthread/cli.h>
42 #include <openthread/icmp6.h>
43 #include <openthread/ip6.h>
44 #include <openthread/link.h>
45 #include <openthread/openthread-system.h>
46 #include <openthread/platform/infra_if.h>
47 #include <openthread/platform/radio.h>
48
49 #include "agent/vendor.hpp"
50 #include "android/otdaemon_telemetry.hpp"
51 #include "common/code_utils.hpp"
52
53 #define BYTE_ARR_END(arr) ((arr) + sizeof(arr))
54
55 namespace otbr {
56
57 namespace vendor {
58
newInstance(Application & aApplication)59 std::shared_ptr<VendorServer> VendorServer::newInstance(Application &aApplication)
60 {
61 return ndk::SharedRefBase::make<Android::OtDaemonServer>(aApplication);
62 }
63
64 } // namespace vendor
65
66 } // namespace otbr
67
68 namespace otbr {
69 namespace Android {
70
71 static const char OTBR_SERVICE_NAME[] = "ot_daemon";
72 static constexpr size_t kMaxIp6Size = 1280;
73
PropagateResult(int aError,const std::string & aMessage,const std::shared_ptr<IOtStatusReceiver> & aReceiver)74 static void PropagateResult(int aError,
75 const std::string &aMessage,
76 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
77 {
78 if (aReceiver != nullptr)
79 {
80 // If an operation has already been requested or accepted, consider it succeeded
81 if (aError == OT_ERROR_NONE || aError == OT_ERROR_ALREADY)
82 {
83 aReceiver->onSuccess();
84 }
85 else
86 {
87 aReceiver->onError(aError, aMessage);
88 }
89 }
90 }
91
ThreadEnabledStateToString(int enabledState)92 static const char *ThreadEnabledStateToString(int enabledState)
93 {
94 switch (enabledState)
95 {
96 case IOtDaemon::OT_STATE_ENABLED:
97 return "ENABLED";
98 case IOtDaemon::OT_STATE_DISABLED:
99 return "DISABLED";
100 case IOtDaemon::OT_STATE_DISABLING:
101 return "DISABLING";
102 default:
103 assert(false);
104 return "UNKNOWN";
105 }
106 }
107
OtDaemonServer(Application & aApplication)108 OtDaemonServer::OtDaemonServer(Application &aApplication)
109 : mApplication(aApplication)
110 , mNcp(aApplication.GetNcp())
111 , mBorderAgent(aApplication.GetBorderAgent())
112 , mMdnsPublisher(static_cast<MdnsPublisher &>(aApplication.GetPublisher()))
113 , mBorderRouterConfiguration()
114 {
115 mClientDeathRecipient =
116 ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&OtDaemonServer::BinderDeathCallback));
117 mBorderRouterConfiguration.infraInterfaceName = "";
118 mBorderRouterConfiguration.infraInterfaceIcmp6Socket = ScopedFileDescriptor();
119 mBorderRouterConfiguration.isBorderRoutingEnabled = false;
120 }
121
Init(void)122 void OtDaemonServer::Init(void)
123 {
124 binder_exception_t exp = AServiceManager_registerLazyService(asBinder().get(), OTBR_SERVICE_NAME);
125 SuccessOrDie(exp, "Failed to register OT daemon binder service");
126
127 assert(GetOtInstance() != nullptr);
128
129 mNcp.AddThreadStateChangedCallback([this](otChangedFlags aFlags) { StateCallback(aFlags); });
130 otIp6SetAddressCallback(GetOtInstance(), OtDaemonServer::AddressCallback, this);
131 otIp6SetReceiveCallback(GetOtInstance(), OtDaemonServer::ReceiveCallback, this);
132 otBackboneRouterSetMulticastListenerCallback(GetOtInstance(), OtDaemonServer::HandleBackboneMulticastListenerEvent,
133 this);
134 otIcmp6SetEchoMode(GetOtInstance(), OT_ICMP6_ECHO_HANDLER_DISABLED);
135 otIp6SetReceiveFilterEnabled(GetOtInstance(), true);
136
137 mTaskRunner.Post(kTelemetryCheckInterval, [this]() { PushTelemetryIfConditionMatch(); });
138 }
139
BinderDeathCallback(void * aBinderServer)140 void OtDaemonServer::BinderDeathCallback(void *aBinderServer)
141 {
142 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
143
144 otbrLogCrit("system_server is dead, removing configs and callbacks...");
145
146 thisServer->mMeshcopTxts = {};
147 thisServer->mINsdPublisher = nullptr;
148
149 // Note that the INsdPublisher reference is held in MdnsPublisher
150 thisServer->mMdnsPublisher.SetINsdPublisher(nullptr);
151
152 thisServer->mCallback = nullptr;
153 thisServer->mTunFd.set(-1); // the original FD will be closed automatically
154 }
155
StateCallback(otChangedFlags aFlags)156 void OtDaemonServer::StateCallback(otChangedFlags aFlags)
157 {
158 std::vector<OnMeshPrefixConfig> onMeshPrefixes;
159
160 assert(GetOtInstance() != nullptr);
161
162 if (RefreshOtDaemonState(aFlags))
163 {
164 if (mCallback == nullptr)
165 {
166 otbrLogWarning("Ignoring OT state changes: callback is not set");
167 }
168 else
169 {
170 mCallback->onStateChanged(mState, -1);
171 }
172 }
173
174 if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
175 {
176 if (mCallback == nullptr)
177 {
178 otbrLogWarning("Ignoring OT backbone router state changes: callback is not set");
179 }
180 else
181 {
182 mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
183 }
184 }
185
186 if ((aFlags & OT_CHANGED_THREAD_NETDATA) && RefreshOnMeshPrefixes())
187 {
188 if (mCallback == nullptr)
189 {
190 otbrLogWarning("Ignoring OT netdata changes: callback is not set");
191 }
192 else
193 {
194 onMeshPrefixes.assign(mOnMeshPrefixes.begin(), mOnMeshPrefixes.end());
195 mCallback->onPrefixChanged(onMeshPrefixes);
196 }
197 }
198 }
199
RefreshOnMeshPrefixes()200 bool OtDaemonServer::RefreshOnMeshPrefixes()
201 {
202 std::set<OnMeshPrefixConfig> onMeshPrefixConfigs;
203 otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
204 otBorderRouterConfig config;
205 bool rv = false;
206
207 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get on mesh prefixes: OT is not initialized"));
208
209 while (otNetDataGetNextOnMeshPrefix(GetOtInstance(), &iterator, &config) == OT_ERROR_NONE)
210 {
211 OnMeshPrefixConfig onMeshPrefixConfig;
212
213 onMeshPrefixConfig.prefix.assign(std::begin(config.mPrefix.mPrefix.mFields.m8),
214 std::end(config.mPrefix.mPrefix.mFields.m8));
215 onMeshPrefixConfig.prefixLength = config.mPrefix.mLength;
216 onMeshPrefixConfigs.insert(onMeshPrefixConfig);
217 }
218
219 if (mOnMeshPrefixes != onMeshPrefixConfigs)
220 {
221 mOnMeshPrefixes = std::move(onMeshPrefixConfigs);
222 rv = true;
223 }
224 exit:
225 return rv;
226 }
227
ConvertToAddressInfo(const otNetifAddress & aAddress)228 Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifAddress &aAddress)
229 {
230 Ipv6AddressInfo addrInfo;
231 otIp6Prefix addressPrefix{aAddress.mAddress, aAddress.mPrefixLength};
232
233 addrInfo.address.assign(std::begin(aAddress.mAddress.mFields.m8), std::end(aAddress.mAddress.mFields.m8));
234 addrInfo.prefixLength = aAddress.mPrefixLength;
235 addrInfo.isPreferred = aAddress.mPreferred;
236 addrInfo.isMeshLocal = aAddress.mMeshLocal;
237 addrInfo.isActiveOmr = otNetDataContainsOmrPrefix(GetOtInstance(), &addressPrefix);
238 return addrInfo;
239 }
240
ConvertToAddressInfo(const otNetifMulticastAddress & aAddress)241 Ipv6AddressInfo OtDaemonServer::ConvertToAddressInfo(const otNetifMulticastAddress &aAddress)
242 {
243 Ipv6AddressInfo addrInfo;
244
245 addrInfo.address.assign(std::begin(aAddress.mAddress.mFields.m8), std::end(aAddress.mAddress.mFields.m8));
246 return addrInfo;
247 }
248
AddressCallback(const otIp6AddressInfo * aAddressInfo,bool aIsAdded,void * aBinderServer)249 void OtDaemonServer::AddressCallback(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aBinderServer)
250 {
251 OT_UNUSED_VARIABLE(aAddressInfo);
252 OT_UNUSED_VARIABLE(aIsAdded);
253 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
254 std::vector<Ipv6AddressInfo> addrInfoList;
255 const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(thisServer->GetOtInstance());
256 const otNetifMulticastAddress *multicastAddrs = otIp6GetMulticastAddresses(thisServer->GetOtInstance());
257
258 for (const otNetifAddress *addr = unicastAddrs; addr != nullptr; addr = addr->mNext)
259 {
260 addrInfoList.push_back(thisServer->ConvertToAddressInfo(*addr));
261 }
262 for (const otNetifMulticastAddress *maddr = multicastAddrs; maddr != nullptr; maddr = maddr->mNext)
263 {
264 addrInfoList.push_back(thisServer->ConvertToAddressInfo(*maddr));
265 }
266 if (thisServer->mCallback != nullptr)
267 {
268 thisServer->mCallback->onAddressChanged(addrInfoList);
269 }
270 else
271 {
272 otbrLogWarning("OT daemon callback is not set");
273 }
274 }
275
ReceiveCallback(otMessage * aMessage,void * aBinderServer)276 void OtDaemonServer::ReceiveCallback(otMessage *aMessage, void *aBinderServer)
277 {
278 static_cast<OtDaemonServer *>(aBinderServer)->ReceiveCallback(aMessage);
279 }
280
281 // FIXME(wgtdkp): We should reuse the same code in openthread/src/posix/platform/netif.cp
282 // after the refactor there is done: https://github.com/openthread/openthread/pull/9293
ReceiveCallback(otMessage * aMessage)283 void OtDaemonServer::ReceiveCallback(otMessage *aMessage)
284 {
285 char packet[kMaxIp6Size];
286 uint16_t length = otMessageGetLength(aMessage);
287 int fd = mTunFd.get();
288
289 VerifyOrExit(fd != -1, otbrLogWarning("Ignoring egress packet: invalid tunnel FD"));
290
291 if (otMessageRead(aMessage, 0, packet, sizeof(packet)) != length)
292 {
293 otbrLogWarning("Failed to read packet from otMessage");
294 ExitNow();
295 }
296
297 if (write(fd, packet, length) != length)
298 {
299 otbrLogWarning("Failed to send packet over tunnel interface: %s", strerror(errno));
300 }
301
302 exit:
303 otMessageFree(aMessage);
304 }
305
306 // FIXME(wgtdkp): this doesn't support NAT64, we should use a shared library with ot-posix
307 // to handle packet translations between the tunnel interface and Thread.
TransmitCallback(void)308 void OtDaemonServer::TransmitCallback(void)
309 {
310 char packet[kMaxIp6Size];
311 ssize_t length;
312 otMessage *message = nullptr;
313 otError error = OT_ERROR_NONE;
314 otMessageSettings settings;
315 int fd = mTunFd.get();
316
317 assert(GetOtInstance() != nullptr);
318
319 VerifyOrExit(fd != -1);
320
321 length = read(fd, packet, sizeof(packet));
322
323 if (length == -1)
324 {
325 otbrLogWarning("Failed to read packet from tunnel interface: %s", strerror(errno));
326 ExitNow();
327 }
328 else if (length == 0)
329 {
330 otbrLogWarning("Unexpected EOF on the tunnel FD");
331 ExitNow();
332 }
333
334 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Ignoring tunnel packet: OT is not initialized"));
335
336 settings.mLinkSecurityEnabled = (otThreadGetDeviceRole(GetOtInstance()) != OT_DEVICE_ROLE_DISABLED);
337 settings.mPriority = OT_MESSAGE_PRIORITY_LOW;
338
339 message = otIp6NewMessage(GetOtInstance(), &settings);
340 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
341 otMessageSetOrigin(message, OT_MESSAGE_ORIGIN_HOST_UNTRUSTED);
342
343 SuccessOrExit(error = otMessageAppend(message, packet, static_cast<uint16_t>(length)));
344
345 error = otIp6Send(GetOtInstance(), message);
346 message = nullptr;
347
348 exit:
349 if (message != nullptr)
350 {
351 otMessageFree(message);
352 }
353
354 if (error != OT_ERROR_NONE)
355 {
356 if (error == OT_ERROR_DROP)
357 {
358 otbrLogInfo("Dropped tunnel packet (length=%d)", length);
359 }
360 else
361 {
362 otbrLogWarning("Failed to transmit tunnel packet: %s", otThreadErrorToString(error));
363 }
364 }
365 }
366
GetBackboneRouterState()367 BackboneRouterState OtDaemonServer::GetBackboneRouterState()
368 {
369 BackboneRouterState state;
370 otBackboneRouterState bbrState;
371 otBackboneRouterMulticastListenerInfo info;
372 otBackboneRouterMulticastListenerIterator iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
373 state.listeningAddresses = std::vector<std::string>();
374
375 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("Can't get bbr state: OT is not initialized"));
376
377 bbrState = otBackboneRouterGetState(GetOtInstance());
378 switch (bbrState)
379 {
380 case OT_BACKBONE_ROUTER_STATE_DISABLED:
381 case OT_BACKBONE_ROUTER_STATE_SECONDARY:
382 state.multicastForwardingEnabled = false;
383 break;
384 case OT_BACKBONE_ROUTER_STATE_PRIMARY:
385 state.multicastForwardingEnabled = true;
386 break;
387 }
388
389 while (otBackboneRouterMulticastListenerGetNext(GetOtInstance(), &iter, &info) == OT_ERROR_NONE)
390 {
391 char string[OT_IP6_ADDRESS_STRING_SIZE];
392
393 otIp6AddressToString(&info.mAddress, string, sizeof(string));
394 state.listeningAddresses.push_back(string);
395 }
396
397 exit:
398 return state;
399 }
400
HandleBackboneMulticastListenerEvent(void * aBinderServer,otBackboneRouterMulticastListenerEvent aEvent,const otIp6Address * aAddress)401 void OtDaemonServer::HandleBackboneMulticastListenerEvent(void *aBinderServer,
402 otBackboneRouterMulticastListenerEvent aEvent,
403 const otIp6Address *aAddress)
404 {
405 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
406 char addressString[OT_IP6_ADDRESS_STRING_SIZE];
407
408 otIp6AddressToString(aAddress, addressString, sizeof(addressString));
409
410 otbrLogInfo("Multicast forwarding address changed, %s is %s", addressString,
411 (aEvent == OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED) ? "added" : "removed");
412
413 if (thisServer->mCallback == nullptr)
414 {
415 otbrLogWarning("Ignoring OT multicast listener event: callback is not set");
416 ExitNow();
417 }
418 thisServer->mCallback->onBackboneRouterStateChanged(thisServer->GetBackboneRouterState());
419
420 exit:
421 return;
422 }
423
GetOtInstance()424 otInstance *OtDaemonServer::GetOtInstance()
425 {
426 return mNcp.GetInstance();
427 }
428
Update(MainloopContext & aMainloop)429 void OtDaemonServer::Update(MainloopContext &aMainloop)
430 {
431 int fd = mTunFd.get();
432
433 if (fd != -1)
434 {
435 FD_SET(fd, &aMainloop.mReadFdSet);
436 aMainloop.mMaxFd = std::max(aMainloop.mMaxFd, fd);
437 }
438 }
439
Process(const MainloopContext & aMainloop)440 void OtDaemonServer::Process(const MainloopContext &aMainloop)
441 {
442 int fd = mTunFd.get();
443
444 if (fd != -1 && FD_ISSET(fd, &aMainloop.mReadFdSet))
445 {
446 TransmitCallback();
447 }
448 }
449
initialize(const ScopedFileDescriptor & aTunFd,const bool enabled,const std::shared_ptr<INsdPublisher> & aINsdPublisher,const MeshcopTxtAttributes & aMeshcopTxts,const std::shared_ptr<IOtDaemonCallback> & aCallback,const std::string & aCountryCode)450 Status OtDaemonServer::initialize(const ScopedFileDescriptor &aTunFd,
451 const bool enabled,
452 const std::shared_ptr<INsdPublisher> &aINsdPublisher,
453 const MeshcopTxtAttributes &aMeshcopTxts,
454 const std::shared_ptr<IOtDaemonCallback> &aCallback,
455 const std::string &aCountryCode)
456 {
457 otbrLogInfo("OT daemon is initialized by system server (tunFd=%d, enabled=%s)", aTunFd.get(),
458 enabled ? "true" : "false");
459 // The copy constructor of `ScopedFileDescriptor` is deleted. It is unable to pass the `aTunFd`
460 // to the lambda function. The processing method of `aTunFd` doesn't call OpenThread functions,
461 // we can process `aTunFd` directly in front of the task.
462 mTunFd = aTunFd.dup();
463
464 mINsdPublisher = aINsdPublisher;
465 mMeshcopTxts = aMeshcopTxts;
466
467 mTaskRunner.Post([enabled, aINsdPublisher, aMeshcopTxts, aCallback, aCountryCode, this]() {
468 initializeInternal(enabled, mINsdPublisher, mMeshcopTxts, aCallback, aCountryCode);
469 });
470
471 return Status::ok();
472 }
473
initializeInternal(const bool enabled,const std::shared_ptr<INsdPublisher> & aINsdPublisher,const MeshcopTxtAttributes & aMeshcopTxts,const std::shared_ptr<IOtDaemonCallback> & aCallback,const std::string & aCountryCode)474 void OtDaemonServer::initializeInternal(const bool enabled,
475 const std::shared_ptr<INsdPublisher> &aINsdPublisher,
476 const MeshcopTxtAttributes &aMeshcopTxts,
477 const std::shared_ptr<IOtDaemonCallback> &aCallback,
478 const std::string &aCountryCode)
479 {
480 std::string instanceName = aMeshcopTxts.vendorName + " " + aMeshcopTxts.modelName;
481 Mdns::Publisher::TxtList nonStandardTxts;
482 otbrError error;
483
484 setCountryCodeInternal(aCountryCode, nullptr /* aReceiver */);
485 registerStateCallbackInternal(aCallback, -1 /* listenerId */);
486
487 mMdnsPublisher.SetINsdPublisher(aINsdPublisher);
488
489 for (const auto &txtAttr : aMeshcopTxts.nonStandardTxtEntries)
490 {
491 nonStandardTxts.emplace_back(txtAttr.name.c_str(), txtAttr.value.data(), txtAttr.value.size());
492 }
493 error = mBorderAgent.SetMeshCopServiceValues(instanceName, aMeshcopTxts.modelName, aMeshcopTxts.vendorName,
494 aMeshcopTxts.vendorOui, nonStandardTxts);
495 if (error != OTBR_ERROR_NONE)
496 {
497 otbrLogCrit("Failed to set MeshCoP values: %d", static_cast<int>(error));
498 }
499
500 mBorderAgent.SetEnabled(enabled);
501
502 if (enabled)
503 {
504 EnableThread(nullptr /* aReceiver */);
505 }
506 else
507 {
508 UpdateThreadEnabledState(OT_STATE_DISABLED, nullptr /* aReceiver */);
509 }
510 }
511
terminate(void)512 Status OtDaemonServer::terminate(void)
513 {
514 mTaskRunner.Post([]() {
515 otbrLogWarning("Terminating ot-daemon process...");
516 exit(0);
517 });
518 return Status::ok();
519 }
520
UpdateThreadEnabledState(const int enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)521 void OtDaemonServer::UpdateThreadEnabledState(const int enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
522 {
523 VerifyOrExit(enabled != mState.threadEnabled);
524
525 otbrLogInfo("Thread enabled state changed: %s -> %s", ThreadEnabledStateToString(mState.threadEnabled),
526 ThreadEnabledStateToString(enabled));
527 mState.threadEnabled = enabled;
528
529 if (aReceiver != nullptr)
530 {
531 aReceiver->onSuccess();
532 }
533
534 // Enables the BorderAgent module only when Thread is enabled because it always
535 // publishes the MeshCoP service even when no Thread network is provisioned.
536 switch (enabled)
537 {
538 case OT_STATE_ENABLED:
539 mBorderAgent.SetEnabled(true);
540 break;
541 case OT_STATE_DISABLED:
542 mBorderAgent.SetEnabled(false);
543 break;
544 }
545
546 if (mCallback != nullptr)
547 {
548 mCallback->onStateChanged(mState, -1);
549 }
550
551 exit:
552 return;
553 }
554
EnableThread(const std::shared_ptr<IOtStatusReceiver> & aReceiver)555 void OtDaemonServer::EnableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
556 {
557 otOperationalDatasetTlvs datasetTlvs;
558
559 if (otDatasetGetActiveTlvs(GetOtInstance(), &datasetTlvs) != OT_ERROR_NOT_FOUND && datasetTlvs.mLength > 0 &&
560 !isAttached())
561 {
562 (void)otIp6SetEnabled(GetOtInstance(), true);
563 (void)otThreadSetEnabled(GetOtInstance(), true);
564 }
565 UpdateThreadEnabledState(OT_STATE_ENABLED, aReceiver);
566 }
567
setThreadEnabled(const bool enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)568 Status OtDaemonServer::setThreadEnabled(const bool enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
569 {
570 mTaskRunner.Post([enabled, aReceiver, this]() { setThreadEnabledInternal(enabled, aReceiver); });
571
572 return Status::ok();
573 }
574
setThreadEnabledInternal(const bool enabled,const std::shared_ptr<IOtStatusReceiver> & aReceiver)575 void OtDaemonServer::setThreadEnabledInternal(const bool enabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver)
576 {
577 int error = OT_ERROR_NONE;
578 std::string message;
579
580 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
581
582 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
583
584 if ((mState.threadEnabled == OT_STATE_ENABLED) == enabled)
585 {
586 aReceiver->onSuccess();
587 ExitNow();
588 }
589
590 if (enabled)
591 {
592 EnableThread(aReceiver);
593 }
594 else
595 {
596 // `aReceiver` should not be set here because the operation isn't finished yet
597 UpdateThreadEnabledState(OT_STATE_DISABLING, nullptr /* aReceiver */);
598
599 LeaveGracefully([aReceiver, this]() {
600 // Ignore errors as those operations should always succeed
601 (void)otThreadSetEnabled(GetOtInstance(), false);
602 (void)otIp6SetEnabled(GetOtInstance(), false);
603 UpdateThreadEnabledState(OT_STATE_DISABLED, aReceiver);
604 });
605 }
606
607 exit:
608 if (error != OT_ERROR_NONE)
609 {
610 PropagateResult(error, message, aReceiver);
611 }
612 }
613
registerStateCallback(const std::shared_ptr<IOtDaemonCallback> & aCallback,int64_t listenerId)614 Status OtDaemonServer::registerStateCallback(const std::shared_ptr<IOtDaemonCallback> &aCallback, int64_t listenerId)
615 {
616 mTaskRunner.Post([aCallback, listenerId, this]() { registerStateCallbackInternal(aCallback, listenerId); });
617
618 return Status::ok();
619 }
620
registerStateCallbackInternal(const std::shared_ptr<IOtDaemonCallback> & aCallback,int64_t listenerId)621 void OtDaemonServer::registerStateCallbackInternal(const std::shared_ptr<IOtDaemonCallback> &aCallback,
622 int64_t listenerId)
623 {
624 VerifyOrExit(GetOtInstance() != nullptr, otbrLogWarning("OT is not initialized"));
625
626 mCallback = aCallback;
627 if (mCallback != nullptr)
628 {
629 AIBinder_linkToDeath(mCallback->asBinder().get(), mClientDeathRecipient.get(), this);
630 }
631
632 // To ensure that a client app can get the latest correct state immediately when registering a
633 // state callback, here needs to invoke the callback
634 RefreshOtDaemonState(/* aFlags */ 0xffffffff);
635 mCallback->onStateChanged(mState, listenerId);
636 mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
637
638 exit:
639 return;
640 }
641
RefreshOtDaemonState(otChangedFlags aFlags)642 bool OtDaemonServer::RefreshOtDaemonState(otChangedFlags aFlags)
643 {
644 bool haveUpdates = false;
645
646 if (aFlags & OT_CHANGED_THREAD_NETIF_STATE)
647 {
648 mState.isInterfaceUp = otIp6IsEnabled(GetOtInstance());
649 haveUpdates = true;
650 }
651
652 if (aFlags & OT_CHANGED_THREAD_ROLE)
653 {
654 mState.deviceRole = otThreadGetDeviceRole(GetOtInstance());
655 haveUpdates = true;
656 }
657
658 if (aFlags & OT_CHANGED_THREAD_PARTITION_ID)
659 {
660 mState.partitionId = otThreadGetPartitionId(GetOtInstance());
661 haveUpdates = true;
662 }
663
664 if (aFlags & OT_CHANGED_ACTIVE_DATASET)
665 {
666 otOperationalDatasetTlvs datasetTlvs;
667 if (otDatasetGetActiveTlvs(GetOtInstance(), &datasetTlvs) == OT_ERROR_NONE)
668 {
669 mState.activeDatasetTlvs.assign(datasetTlvs.mTlvs, datasetTlvs.mTlvs + datasetTlvs.mLength);
670 }
671 else
672 {
673 mState.activeDatasetTlvs.clear();
674 }
675 haveUpdates = true;
676 }
677
678 if (aFlags & OT_CHANGED_PENDING_DATASET)
679 {
680 otOperationalDatasetTlvs datasetTlvs;
681 if (otDatasetGetPendingTlvs(GetOtInstance(), &datasetTlvs) == OT_ERROR_NONE)
682 {
683 mState.pendingDatasetTlvs.assign(datasetTlvs.mTlvs, datasetTlvs.mTlvs + datasetTlvs.mLength);
684 }
685 else
686 {
687 mState.pendingDatasetTlvs.clear();
688 }
689 haveUpdates = true;
690 }
691
692 if (isAttached() && !mState.activeDatasetTlvs.empty() && mJoinReceiver != nullptr)
693 {
694 otbrLogInfo("Join succeeded");
695 mJoinReceiver->onSuccess();
696 mJoinReceiver = nullptr;
697 }
698
699 return haveUpdates;
700 }
701
join(const std::vector<uint8_t> & aActiveOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)702 Status OtDaemonServer::join(const std::vector<uint8_t> &aActiveOpDatasetTlvs,
703 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
704 {
705 mTaskRunner.Post([aActiveOpDatasetTlvs, aReceiver, this]() { joinInternal(aActiveOpDatasetTlvs, aReceiver); });
706
707 return Status::ok();
708 }
709
joinInternal(const std::vector<uint8_t> & aActiveOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)710 void OtDaemonServer::joinInternal(const std::vector<uint8_t> &aActiveOpDatasetTlvs,
711 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
712 {
713 int error = OT_ERROR_NONE;
714 std::string message;
715 otOperationalDatasetTlvs datasetTlvs;
716
717 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
718
719 VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED,
720 error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED),
721 message = "Thread is disabled");
722
723 otbrLogInfo("Start joining...");
724
725 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
726
727 if (otThreadGetDeviceRole(GetOtInstance()) != OT_DEVICE_ROLE_DISABLED)
728 {
729 LeaveGracefully([aActiveOpDatasetTlvs, aReceiver, this]() {
730 FinishLeave(nullptr);
731 join(aActiveOpDatasetTlvs, aReceiver);
732 });
733 ExitNow();
734 }
735
736 std::copy(aActiveOpDatasetTlvs.begin(), aActiveOpDatasetTlvs.end(), datasetTlvs.mTlvs);
737 datasetTlvs.mLength = static_cast<uint8_t>(aActiveOpDatasetTlvs.size());
738 SuccessOrExit(error = otDatasetSetActiveTlvs(GetOtInstance(), &datasetTlvs),
739 message = "Failed to set Active Operational Dataset");
740
741 // TODO(b/273160198): check how we can implement join as a child
742
743 // Shouldn't we have an equivalent `otThreadAttach` method vs `otThreadDetachGracefully`?
744 SuccessOrExit(error = otIp6SetEnabled(GetOtInstance(), true), message = "Failed to bring up Thread interface");
745 SuccessOrExit(error = otThreadSetEnabled(GetOtInstance(), true), message = "Failed to bring up Thread stack");
746
747 // Abort an ongoing join()
748 if (mJoinReceiver != nullptr)
749 {
750 mJoinReceiver->onError(OT_ERROR_ABORT, "Join() is aborted");
751 }
752 mJoinReceiver = aReceiver;
753
754 exit:
755 if (error != OT_ERROR_NONE)
756 {
757 PropagateResult(error, message, aReceiver);
758 }
759 }
760
leave(const std::shared_ptr<IOtStatusReceiver> & aReceiver)761 Status OtDaemonServer::leave(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
762 {
763 mTaskRunner.Post([aReceiver, this]() { leaveInternal(aReceiver); });
764
765 return Status::ok();
766 }
767
leaveInternal(const std::shared_ptr<IOtStatusReceiver> & aReceiver)768 void OtDaemonServer::leaveInternal(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
769 {
770 std::string message;
771 int error = OT_ERROR_NONE;
772
773 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
774
775 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
776
777 if (mState.threadEnabled == OT_STATE_DISABLED)
778 {
779 FinishLeave(aReceiver);
780 ExitNow();
781 }
782
783 LeaveGracefully([aReceiver, this]() { FinishLeave(aReceiver); });
784
785 exit:
786 if (error != OT_ERROR_NONE)
787 {
788 PropagateResult(error, message, aReceiver);
789 }
790 }
791
FinishLeave(const std::shared_ptr<IOtStatusReceiver> & aReceiver)792 void OtDaemonServer::FinishLeave(const std::shared_ptr<IOtStatusReceiver> &aReceiver)
793 {
794 (void)otInstanceErasePersistentInfo(GetOtInstance());
795 OT_UNUSED_VARIABLE(mApplication); // Avoid the unused-private-field issue.
796 // TODO: b/323301831 - Re-init the Application class.
797 if (aReceiver != nullptr)
798 {
799 aReceiver->onSuccess();
800 }
801 }
802
LeaveGracefully(const LeaveCallback & aReceiver)803 void OtDaemonServer::LeaveGracefully(const LeaveCallback &aReceiver)
804 {
805 mLeaveCallbacks.push_back(aReceiver);
806
807 // Ignores the OT_ERROR_BUSY error if a detach has already been requested
808 (void)otThreadDetachGracefully(GetOtInstance(), DetachGracefullyCallback, this);
809 }
810
DetachGracefullyCallback(void * aBinderServer)811 void OtDaemonServer::DetachGracefullyCallback(void *aBinderServer)
812 {
813 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
814 thisServer->DetachGracefullyCallback();
815 }
816
DetachGracefullyCallback(void)817 void OtDaemonServer::DetachGracefullyCallback(void)
818 {
819 otbrLogInfo("detach success...");
820
821 if (mJoinReceiver != nullptr)
822 {
823 mJoinReceiver->onError(OT_ERROR_ABORT, "Aborted by leave/disable operation");
824 mJoinReceiver = nullptr;
825 }
826
827 if (mMigrationReceiver != nullptr)
828 {
829 mMigrationReceiver->onError(OT_ERROR_ABORT, "Aborted by leave/disable operation");
830 mMigrationReceiver = nullptr;
831 }
832
833 for (auto &callback : mLeaveCallbacks)
834 {
835 callback();
836 }
837 mLeaveCallbacks.clear();
838 }
839
isAttached()840 bool OtDaemonServer::isAttached()
841 {
842 otDeviceRole role = otThreadGetDeviceRole(GetOtInstance());
843
844 return role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER;
845 }
846
scheduleMigration(const std::vector<uint8_t> & aPendingOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)847 Status OtDaemonServer::scheduleMigration(const std::vector<uint8_t> &aPendingOpDatasetTlvs,
848 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
849 {
850 mTaskRunner.Post(
851 [aPendingOpDatasetTlvs, aReceiver, this]() { scheduleMigrationInternal(aPendingOpDatasetTlvs, aReceiver); });
852
853 return Status::ok();
854 }
855
scheduleMigrationInternal(const std::vector<uint8_t> & aPendingOpDatasetTlvs,const std::shared_ptr<IOtStatusReceiver> & aReceiver)856 void OtDaemonServer::scheduleMigrationInternal(const std::vector<uint8_t> &aPendingOpDatasetTlvs,
857 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
858 {
859 int error = OT_ERROR_NONE;
860 std::string message;
861 otOperationalDataset emptyDataset;
862
863 VerifyOrExit(mState.threadEnabled != OT_STATE_DISABLING, error = OT_ERROR_BUSY, message = "Thread is disabling");
864
865 VerifyOrExit(mState.threadEnabled == OT_STATE_ENABLED,
866 error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_THREAD_DISABLED),
867 message = "Thread is disabled");
868
869 if (GetOtInstance() == nullptr)
870 {
871 message = "OT is not initialized";
872 ExitNow(error = OT_ERROR_INVALID_STATE);
873 }
874 if (!isAttached())
875 {
876 message = "Cannot schedule migration when this device is detached";
877 ExitNow(error = static_cast<int>(IOtDaemon::ErrorCode::OT_ERROR_FAILED_PRECONDITION));
878 }
879
880 // TODO: check supported channel mask
881
882 error = otDatasetSendMgmtPendingSet(GetOtInstance(), &emptyDataset, aPendingOpDatasetTlvs.data(),
883 static_cast<uint8_t>(aPendingOpDatasetTlvs.size()), SendMgmtPendingSetCallback,
884 /* aBinderServer= */ this);
885 if (error != OT_ERROR_NONE)
886 {
887 message = "Failed to send MGMT_PENDING_SET.req";
888 }
889
890 exit:
891 if (error != OT_ERROR_NONE)
892 {
893 PropagateResult(error, message, aReceiver);
894 }
895 else
896 {
897 // otDatasetSendMgmtPendingSet() returns OT_ERROR_BUSY if it has already been called before but the
898 // callback hasn't been invoked. So we can guarantee that mMigrationReceiver is always nullptr here
899 assert(mMigrationReceiver == nullptr);
900 mMigrationReceiver = aReceiver;
901 }
902 }
903
SendMgmtPendingSetCallback(otError aResult,void * aBinderServer)904 void OtDaemonServer::SendMgmtPendingSetCallback(otError aResult, void *aBinderServer)
905 {
906 OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
907
908 if (thisServer->mMigrationReceiver != nullptr)
909 {
910 PropagateResult(aResult, "Failed to register Pending Dataset to leader", thisServer->mMigrationReceiver);
911 thisServer->mMigrationReceiver = nullptr;
912 }
913 }
914
setCountryCode(const std::string & aCountryCode,const std::shared_ptr<IOtStatusReceiver> & aReceiver)915 Status OtDaemonServer::setCountryCode(const std::string &aCountryCode,
916 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
917 {
918 mTaskRunner.Post([aCountryCode, aReceiver, this]() { setCountryCodeInternal(aCountryCode, aReceiver); });
919
920 return Status::ok();
921 }
922
setCountryCodeInternal(const std::string & aCountryCode,const std::shared_ptr<IOtStatusReceiver> & aReceiver)923 void OtDaemonServer::setCountryCodeInternal(const std::string &aCountryCode,
924 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
925 {
926 static constexpr int kCountryCodeLength = 2;
927 otError error = OT_ERROR_NONE;
928 std::string message;
929 uint16_t countryCode;
930
931 VerifyOrExit((aCountryCode.length() == kCountryCodeLength) && isalpha(aCountryCode[0]) && isalpha(aCountryCode[1]),
932 error = OT_ERROR_INVALID_ARGS, message = "The country code is invalid");
933
934 otbrLogInfo("Set country code: %c%c", aCountryCode[0], aCountryCode[1]);
935 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
936
937 countryCode = static_cast<uint16_t>((aCountryCode[0] << 8) | aCountryCode[1]);
938 SuccessOrExit(error = otLinkSetRegion(GetOtInstance(), countryCode), message = "Failed to set the country code");
939
940 exit:
941 PropagateResult(error, message, aReceiver);
942 }
943
getChannelMasks(const std::shared_ptr<IChannelMasksReceiver> & aReceiver)944 Status OtDaemonServer::getChannelMasks(const std::shared_ptr<IChannelMasksReceiver> &aReceiver)
945 {
946 mTaskRunner.Post([aReceiver, this]() { getChannelMasksInternal(aReceiver); });
947
948 return Status::ok();
949 }
950
getChannelMasksInternal(const std::shared_ptr<IChannelMasksReceiver> & aReceiver)951 void OtDaemonServer::getChannelMasksInternal(const std::shared_ptr<IChannelMasksReceiver> &aReceiver)
952 {
953 otError error = OT_ERROR_NONE;
954 uint32_t supportedChannelMask;
955 uint32_t preferredChannelMask;
956
957 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE);
958
959 supportedChannelMask = otLinkGetSupportedChannelMask(GetOtInstance());
960 preferredChannelMask = otPlatRadioGetPreferredChannelMask(GetOtInstance());
961
962 exit:
963 if (aReceiver != nullptr)
964 {
965 if (error == OT_ERROR_NONE)
966 {
967 aReceiver->onSuccess(supportedChannelMask, preferredChannelMask);
968 }
969 else
970 {
971 aReceiver->onError(error, "OT is not initialized");
972 }
973 }
974 }
975
setChannelMaxPowers(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)976 Status OtDaemonServer::setChannelMaxPowers(const std::vector<ChannelMaxPower> &aChannelMaxPowers,
977 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
978 {
979 mTaskRunner.Post(
980 [aChannelMaxPowers, aReceiver, this]() { setChannelMaxPowersInternal(aChannelMaxPowers, aReceiver); });
981
982 return Status::ok();
983 }
984
setChannelMaxPowersInternal(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const std::shared_ptr<IOtStatusReceiver> & aReceiver)985 Status OtDaemonServer::setChannelMaxPowersInternal(const std::vector<ChannelMaxPower> &aChannelMaxPowers,
986 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
987 {
988 otError error = OT_ERROR_NONE;
989 std::string message;
990 uint8_t channel;
991 int16_t maxPower;
992
993 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
994
995 for (ChannelMaxPower channelMaxPower : aChannelMaxPowers)
996 {
997 VerifyOrExit((channelMaxPower.channel >= OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN) &&
998 (channelMaxPower.channel <= OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX),
999 error = OT_ERROR_INVALID_ARGS, message = "The channel is invalid");
1000 VerifyOrExit((channelMaxPower.maxPower >= INT16_MIN) && (channelMaxPower.maxPower <= INT16_MAX),
1001 error = OT_ERROR_INVALID_ARGS, message = "The max power is invalid");
1002 }
1003
1004 for (ChannelMaxPower channelMaxPower : aChannelMaxPowers)
1005 {
1006 channel = static_cast<uint8_t>(channelMaxPower.channel);
1007 maxPower = static_cast<int16_t>(channelMaxPower.maxPower);
1008 otbrLogInfo("Set channel max power: channel=%u, maxPower=%d", channel, maxPower);
1009 SuccessOrExit(error = otPlatRadioSetChannelTargetPower(GetOtInstance(), channel, maxPower),
1010 message = "Failed to set channel max power");
1011 }
1012
1013 exit:
1014 PropagateResult(error, message, aReceiver);
1015 return Status::ok();
1016 }
1017
configureBorderRouter(const BorderRouterConfigurationParcel & aBorderRouterConfiguration,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1018 Status OtDaemonServer::configureBorderRouter(const BorderRouterConfigurationParcel &aBorderRouterConfiguration,
1019 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1020 {
1021 int icmp6SocketFd = aBorderRouterConfiguration.infraInterfaceIcmp6Socket.dup().release();
1022 std::string infraInterfaceName = aBorderRouterConfiguration.infraInterfaceName;
1023 bool isBorderRoutingEnabled = aBorderRouterConfiguration.isBorderRoutingEnabled;
1024 bool isBorderRouterConfigChanged = (mBorderRouterConfiguration != aBorderRouterConfiguration);
1025
1026 otbrLogInfo("Configuring Border Router: %s", aBorderRouterConfiguration.toString().c_str());
1027
1028 // The copy constructor of `BorderRouterConfigurationParcel` is deleted. It is unable to directly pass the
1029 // `aBorderRouterConfiguration` to the lambda function. Only the necessary parameters of
1030 // `BorderRouterConfigurationParcel` are passed to the lambda function here.
1031 mTaskRunner.Post(
1032 [icmp6SocketFd, infraInterfaceName, isBorderRoutingEnabled, isBorderRouterConfigChanged, aReceiver, this]() {
1033 configureBorderRouterInternal(icmp6SocketFd, infraInterfaceName, isBorderRoutingEnabled,
1034 isBorderRouterConfigChanged, aReceiver);
1035 });
1036
1037 return Status::ok();
1038 }
1039
configureBorderRouterInternal(int aIcmp6SocketFd,const std::string & aInfraInterfaceName,bool aIsBorderRoutingEnabled,bool aIsBorderRouterConfigChanged,const std::shared_ptr<IOtStatusReceiver> & aReceiver)1040 void OtDaemonServer::configureBorderRouterInternal(int aIcmp6SocketFd,
1041 const std::string &aInfraInterfaceName,
1042 bool aIsBorderRoutingEnabled,
1043 bool aIsBorderRouterConfigChanged,
1044 const std::shared_ptr<IOtStatusReceiver> &aReceiver)
1045 {
1046 int icmp6SocketFd = aIcmp6SocketFd;
1047 otError error = OT_ERROR_NONE;
1048 std::string message;
1049
1050 VerifyOrExit(GetOtInstance() != nullptr, error = OT_ERROR_INVALID_STATE, message = "OT is not initialized");
1051
1052 if (aIsBorderRouterConfigChanged)
1053 {
1054 if (aIsBorderRoutingEnabled)
1055 {
1056 unsigned int infraIfIndex = if_nametoindex(aInfraInterfaceName.c_str());
1057 SuccessOrExit(error = otBorderRoutingSetEnabled(GetOtInstance(), false /* aEnabled */),
1058 message = "failed to disable border routing");
1059 otSysSetInfraNetif(aInfraInterfaceName.c_str(), icmp6SocketFd);
1060 icmp6SocketFd = -1;
1061 SuccessOrExit(error = otBorderRoutingInit(GetOtInstance(), infraIfIndex, otSysInfraIfIsRunning()),
1062 message = "failed to initialize border routing");
1063 SuccessOrExit(error = otBorderRoutingSetEnabled(GetOtInstance(), true /* aEnabled */),
1064 message = "failed to enable border routing");
1065 // TODO: b/320836258 - Make BBR independently configurable
1066 otBackboneRouterSetEnabled(GetOtInstance(), true /* aEnabled */);
1067 }
1068 else
1069 {
1070 SuccessOrExit(error = otBorderRoutingSetEnabled(GetOtInstance(), false /* aEnabled */),
1071 message = "failed to disable border routing");
1072 otBackboneRouterSetEnabled(GetOtInstance(), false /* aEnabled */);
1073 }
1074 }
1075
1076 mBorderRouterConfiguration.isBorderRoutingEnabled = aIsBorderRoutingEnabled;
1077 mBorderRouterConfiguration.infraInterfaceName = aInfraInterfaceName;
1078
1079 exit:
1080 if (error != OT_ERROR_NONE)
1081 {
1082 close(icmp6SocketFd);
1083 }
1084 PropagateResult(error, message, aReceiver);
1085 }
1086
OutputCallback(void * aContext,const char * aFormat,va_list aArguments)1087 static int OutputCallback(void *aContext, const char *aFormat, va_list aArguments)
1088 {
1089 std::string output;
1090
1091 android::base::StringAppendV(&output, aFormat, aArguments);
1092
1093 int length = output.length();
1094
1095 VerifyOrExit(android::base::WriteStringToFd(output, *(static_cast<int *>(aContext))), length = 0);
1096
1097 exit:
1098 return length;
1099 }
1100
DumpCliCommand(std::string aCommand,int aFd)1101 inline void DumpCliCommand(std::string aCommand, int aFd)
1102 {
1103 android::base::WriteStringToFd(aCommand + '\n', aFd);
1104 otCliInputLine(aCommand.data());
1105 }
1106
dump(int aFd,const char ** aArgs,uint32_t aNumArgs)1107 binder_status_t OtDaemonServer::dump(int aFd, const char **aArgs, uint32_t aNumArgs)
1108 {
1109 OT_UNUSED_VARIABLE(aArgs);
1110 OT_UNUSED_VARIABLE(aNumArgs);
1111
1112 otCliInit(GetOtInstance(), OutputCallback, &aFd);
1113
1114 DumpCliCommand("state", aFd);
1115 DumpCliCommand("srp server state", aFd);
1116 DumpCliCommand("srp server service", aFd);
1117 DumpCliCommand("srp server host", aFd);
1118 DumpCliCommand("dataset active", aFd);
1119 DumpCliCommand("leaderdata", aFd);
1120 DumpCliCommand("eidcache", aFd);
1121 DumpCliCommand("counters mac", aFd);
1122 DumpCliCommand("counters mle", aFd);
1123 DumpCliCommand("counters ip", aFd);
1124 DumpCliCommand("router table", aFd);
1125 DumpCliCommand("neighbor table", aFd);
1126 DumpCliCommand("ipaddr -v", aFd);
1127 DumpCliCommand("netdata show", aFd);
1128
1129 fsync(aFd);
1130
1131 otSysCliInitUsingDaemon(GetOtInstance());
1132
1133 return STATUS_OK;
1134 }
1135
PushTelemetryIfConditionMatch()1136 void OtDaemonServer::PushTelemetryIfConditionMatch()
1137 {
1138 VerifyOrExit(GetOtInstance() != nullptr);
1139
1140 // TODO: Push telemetry per kTelemetryUploadIntervalThreshold instead of on startup.
1141 // TODO: Save unpushed telemetries in local cache to avoid data loss.
1142 RetrieveAndPushAtoms(GetOtInstance());
1143 mTaskRunner.Post(kTelemetryUploadIntervalThreshold, [this]() { PushTelemetryIfConditionMatch(); });
1144
1145 exit:
1146 return;
1147 }
1148
1149 } // namespace Android
1150 } // namespace otbr
1151