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 contains definitions for the CLI interpreter.
32 */
33
34 #ifndef CLI_HPP_
35 #define CLI_HPP_
36
37 #include "openthread-core-config.h"
38
39 #include "cli_config.h"
40
41 #include <stdarg.h>
42
43 #include <openthread/cli.h>
44 #include <openthread/dataset.h>
45 #include <openthread/dns_client.h>
46 #include <openthread/instance.h>
47 #include <openthread/ip6.h>
48 #include <openthread/link.h>
49 #include <openthread/logging.h>
50 #include <openthread/mesh_diag.h>
51 #include <openthread/netdata.h>
52 #include <openthread/ping_sender.h>
53 #include <openthread/sntp.h>
54 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
55 #include <openthread/tcp.h>
56 #endif
57 #include <openthread/thread.h>
58 #include <openthread/thread_ftd.h>
59 #include <openthread/udp.h>
60
61 #include "cli/cli_bbr.hpp"
62 #include "cli/cli_br.hpp"
63 #include "cli/cli_commissioner.hpp"
64 #include "cli/cli_dataset.hpp"
65 #include "cli/cli_dns.hpp"
66 #include "cli/cli_history.hpp"
67 #include "cli/cli_joiner.hpp"
68 #include "cli/cli_link_metrics.hpp"
69 #include "cli/cli_mac_filter.hpp"
70 #include "cli/cli_network_data.hpp"
71 #include "cli/cli_output.hpp"
72 #include "cli/cli_ping.hpp"
73 #include "cli/cli_srp_client.hpp"
74 #include "cli/cli_srp_server.hpp"
75 #include "cli/cli_tcat.hpp"
76 #include "cli/cli_tcp.hpp"
77 #include "cli/cli_udp.hpp"
78 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
79 #include "cli/cli_coap.hpp"
80 #endif
81 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
82 #include "cli/cli_coap_secure.hpp"
83 #endif
84
85 #include "common/array.hpp"
86 #include "common/code_utils.hpp"
87 #include "common/debug.hpp"
88 #include "common/type_traits.hpp"
89 #include "instance/instance.hpp"
90
91 namespace ot {
92
93 /**
94 * @namespace ot::Cli
95 *
96 * @brief
97 * This namespace contains definitions for the CLI interpreter.
98 *
99 */
100 namespace Cli {
101
102 extern "C" void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list);
103 extern "C" void otCliAppendResult(otError aError);
104 extern "C" void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
105 extern "C" void otCliOutputFormat(const char *aFmt, ...);
106
107 /**
108 * Implements the CLI interpreter.
109 *
110 */
111 class Interpreter : public OutputImplementer, public Output
112 {
113 #if OPENTHREAD_FTD || OPENTHREAD_MTD
114 friend class Br;
115 friend class Bbr;
116 friend class Commissioner;
117 friend class Dns;
118 friend class Joiner;
119 friend class LinkMetrics;
120 friend class NetworkData;
121 friend class PingSender;
122 friend class SrpClient;
123 friend class SrpServer;
124 #endif
125 friend void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list);
126 friend void otCliAppendResult(otError aError);
127 friend void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
128 friend void otCliOutputFormat(const char *aFmt, ...);
129
130 public:
131 typedef Utils::CmdLineParser::Arg Arg;
132
133 /**
134 * Constructor
135 *
136 * @param[in] aInstance The OpenThread instance structure.
137 * @param[in] aCallback A callback method called to process CLI output.
138 * @param[in] aContext A user context pointer.
139 */
140 explicit Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext);
141
142 /**
143 * Returns a reference to the interpreter object.
144 *
145 * @returns A reference to the interpreter object.
146 *
147 */
GetInterpreter(void)148 static Interpreter &GetInterpreter(void)
149 {
150 OT_ASSERT(sInterpreter != nullptr);
151
152 return *sInterpreter;
153 }
154
155 /**
156 * Initializes the Console interpreter.
157 *
158 * @param[in] aInstance The OpenThread instance structure.
159 * @param[in] aCallback A pointer to a callback method.
160 * @param[in] aContext A pointer to a user context.
161 *
162 */
163 static void Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
164
165 /**
166 * Returns whether the interpreter is initialized.
167 *
168 * @returns Whether the interpreter is initialized.
169 *
170 */
IsInitialized(void)171 static bool IsInitialized(void) { return sInterpreter != nullptr; }
172
173 /**
174 * Interprets a CLI command.
175 *
176 * @param[in] aBuf A pointer to a string.
177 *
178 */
179 void ProcessLine(char *aBuf);
180
181 /**
182 * Checks a given argument string against "enable" or "disable" commands.
183 *
184 * @param[in] aArg The argument string to parse.
185 * @param[out] aEnable Boolean variable to return outcome on success.
186 * Set to TRUE for "enable" command, and FALSE for "disable" command.
187 *
188 * @retval OT_ERROR_NONE Successfully parsed the @p aString and updated @p aEnable.
189 * @retval OT_ERROR_INVALID_COMMAND The @p aString is not "enable" or "disable" command.
190 *
191 */
192 static otError ParseEnableOrDisable(const Arg &aArg, bool &aEnable);
193
194 /**
195 * Adds commands to the user command table.
196 *
197 * @param[in] aCommands A pointer to an array with user commands.
198 * @param[in] aLength @p aUserCommands length.
199 * @param[in] aContext @p aUserCommands length.
200 *
201 * @retval OT_ERROR_NONE Successfully updated command table with commands from @p aCommands.
202 * @retval OT_ERROR_FAILED No available UserCommandsEntry to register requested user commands.
203 */
204 otError SetUserCommands(const otCliCommand *aCommands, uint8_t aLength, void *aContext);
205
206 static constexpr uint8_t kLinkModeStringSize = sizeof("rdn"); ///< Size of string buffer for a MLE Link Mode.
207
208 /**
209 * Converts a given MLE Link Mode to flag string.
210 *
211 * The characters 'r', 'd', and 'n' are respectively used for `mRxOnWhenIdle`, `mDeviceType` and `mNetworkData`
212 * flags. If all flags are `false`, then "-" is returned.
213 *
214 * @param[in] aLinkMode The MLE Link Mode to convert.
215 * @param[out] aStringBuffer A reference to an string array to place the string.
216 *
217 * @returns A pointer @p aStringBuffer which contains the converted string.
218 *
219 */
220 static const char *LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize]);
221
222 /**
223 * Converts an IPv6 address origin `OT_ADDRESS_ORIGIN_*` value to human-readable string.
224 *
225 * @param[in] aOrigin The IPv6 address origin to convert.
226 *
227 * @returns A human-readable string representation of @p aOrigin.
228 *
229 */
230 static const char *AddressOriginToString(uint8_t aOrigin);
231
232 /**
233 * Parses a given argument string as a route preference comparing it against "high", "med", or
234 * "low".
235 *
236 * @param[in] aArg The argument string to parse.
237 * @param[out] aPreference Reference to a `otRoutePreference` to return the parsed preference.
238 *
239 * @retval OT_ERROR_NONE Successfully parsed @p aArg and updated @p aPreference.
240 * @retval OT_ERROR_INVALID_ARG @p aArg is not a valid preference string "high", "med", or "low".
241 *
242 */
243 static otError ParsePreference(const Arg &aArg, otRoutePreference &aPreference);
244
245 /**
246 * Converts a route preference value to human-readable string.
247 *
248 * @param[in] aPreference The preference value to convert (`OT_ROUTE_PREFERENCE_*` values).
249 *
250 * @returns A string representation @p aPreference.
251 *
252 */
253 static const char *PreferenceToString(signed int aPreference);
254
255 /**
256 * Parses the argument as an IP address.
257 *
258 * If the argument string is an IPv4 address, this method will try to synthesize an IPv6 address using preferred
259 * NAT64 prefix in the network data.
260 *
261 * @param[in] aInstance A pointer to openthread instance.
262 * @param[in] aArg The argument string to parse.
263 * @param[out] aAddress A reference to an `otIp6Address` to output the parsed IPv6 address.
264 * @param[out] aSynthesized Whether @p aAddress is synthesized from an IPv4 address.
265 *
266 * @retval OT_ERROR_NONE The argument was parsed successfully.
267 * @retval OT_ERROR_INVALID_ARGS The argument is empty or does not contain valid IP address.
268 * @retval OT_ERROR_INVALID_STATE No valid NAT64 prefix in the network data.
269 *
270 */
271 static otError ParseToIp6Address(otInstance *aInstance,
272 const Arg &aArg,
273 otIp6Address &aAddress,
274 bool &aSynthesized);
275
276 protected:
277 static Interpreter *sInterpreter;
278
279 private:
280 static constexpr uint8_t kIndentSize = 4;
281 static constexpr uint16_t kMaxArgs = 32;
282 static constexpr uint16_t kMaxLineLength = OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH;
283 static constexpr uint16_t kMaxUserCommandEntries = OPENTHREAD_CONFIG_CLI_MAX_USER_CMD_ENTRIES;
284
285 static constexpr uint32_t kNetworkDiagnosticTimeoutMsecs = 5000;
286 static constexpr uint32_t kLocateTimeoutMsecs = 2500;
287
288 static constexpr uint16_t kMaxTxtDataSize = OPENTHREAD_CONFIG_CLI_TXT_RECORD_MAX_SIZE;
289
290 using Command = CommandEntry<Interpreter>;
291
292 template <typename ValueType> using GetHandler = ValueType (&)(otInstance *);
293 template <typename ValueType> using SetHandler = void (&)(otInstance *, ValueType);
294 template <typename ValueType> using SetHandlerFailable = otError (&)(otInstance *, ValueType);
295 using IsEnabledHandler = bool (&)(otInstance *);
296 using SetEnabledHandler = void (&)(otInstance *, bool);
297 using SetEnabledHandlerFailable = otError (&)(otInstance *, bool);
298
299 // Returns format string to output a `ValueType` (e.g., "%u" for `uint16_t`).
300 template <typename ValueType> static constexpr const char *FormatStringFor(void);
301
302 // General template implementation.
303 // Specializations for `uint32_t` and `int32_t` are added at the end.
ProcessGet(Arg aArgs[],GetHandler<ValueType> aGetHandler)304 template <typename ValueType> otError ProcessGet(Arg aArgs[], GetHandler<ValueType> aGetHandler)
305 {
306 static_assert(
307 TypeTraits::IsSame<ValueType, uint8_t>::kValue || TypeTraits::IsSame<ValueType, uint16_t>::kValue ||
308 TypeTraits::IsSame<ValueType, int8_t>::kValue || TypeTraits::IsSame<ValueType, int16_t>::kValue ||
309 TypeTraits::IsSame<ValueType, const char *>::kValue,
310 "ValueType must be an 8, 16 `int` or `uint` type, or a `const char *`");
311
312 otError error = OT_ERROR_NONE;
313
314 VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
315 OutputLine(FormatStringFor<ValueType>(), aGetHandler(GetInstancePtr()));
316
317 exit:
318 return error;
319 }
320
ProcessSet(Arg aArgs[],SetHandler<ValueType> aSetHandler)321 template <typename ValueType> otError ProcessSet(Arg aArgs[], SetHandler<ValueType> aSetHandler)
322 {
323 otError error;
324 ValueType value;
325
326 SuccessOrExit(error = aArgs[0].ParseAs<ValueType>(value));
327 VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
328
329 aSetHandler(GetInstancePtr(), value);
330
331 exit:
332 return error;
333 }
334
ProcessSet(Arg aArgs[],SetHandlerFailable<ValueType> aSetHandler)335 template <typename ValueType> otError ProcessSet(Arg aArgs[], SetHandlerFailable<ValueType> aSetHandler)
336 {
337 otError error;
338 ValueType value;
339
340 SuccessOrExit(error = aArgs[0].ParseAs<ValueType>(value));
341 VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
342
343 error = aSetHandler(GetInstancePtr(), value);
344
345 exit:
346 return error;
347 }
348
349 template <typename ValueType>
ProcessGetSet(Arg aArgs[],GetHandler<ValueType> aGetHandler,SetHandler<ValueType> aSetHandler)350 otError ProcessGetSet(Arg aArgs[], GetHandler<ValueType> aGetHandler, SetHandler<ValueType> aSetHandler)
351 {
352 otError error = ProcessGet(aArgs, aGetHandler);
353
354 VerifyOrExit(error != OT_ERROR_NONE);
355 error = ProcessSet(aArgs, aSetHandler);
356
357 exit:
358 return error;
359 }
360
361 template <typename ValueType>
ProcessGetSet(Arg aArgs[],GetHandler<ValueType> aGetHandler,SetHandlerFailable<ValueType> aSetHandler)362 otError ProcessGetSet(Arg aArgs[], GetHandler<ValueType> aGetHandler, SetHandlerFailable<ValueType> aSetHandler)
363 {
364 otError error = ProcessGet(aArgs, aGetHandler);
365
366 VerifyOrExit(error != OT_ERROR_NONE);
367 error = ProcessSet(aArgs, aSetHandler);
368
369 exit:
370 return error;
371 }
372
373 otError ProcessEnableDisable(Arg aArgs[], SetEnabledHandler aSetEnabledHandler);
374 otError ProcessEnableDisable(Arg aArgs[], SetEnabledHandlerFailable aSetEnabledHandler);
375 otError ProcessEnableDisable(Arg aArgs[], IsEnabledHandler aIsEnabledHandler, SetEnabledHandler aSetEnabledHandler);
376 otError ProcessEnableDisable(Arg aArgs[],
377 IsEnabledHandler aIsEnabledHandler,
378 SetEnabledHandlerFailable aSetEnabledHandler);
379
380 void OutputPrompt(void);
381 void OutputResult(otError aError);
382
383 static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
384 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
385 static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig);
386 static otError ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig);
387 #endif
388 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
389 void OutputBorderRouterCounters(void);
390 #endif
391
392 otError ProcessCommand(Arg aArgs[]);
393
394 template <CommandId kCommandId> otError Process(Arg aArgs[]);
395
396 otError ProcessUserCommands(Arg aArgs[]);
397
398 #if OPENTHREAD_FTD || OPENTHREAD_MTD
399
400 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
401 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
402 otError ProcessBackboneRouterLocal(Arg aArgs[]);
403 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
404 otError ProcessBackboneRouterMgmtMlr(Arg aArgs[]);
405 void PrintMulticastListenersTable(void);
406 #endif
407 #endif
408 #endif
409
410 #if OPENTHREAD_FTD
411 void OutputEidCacheEntry(const otCacheEntryInfo &aEntry);
412 #endif
413 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
414 static void HandleLocateResult(void *aContext,
415 otError aError,
416 const otIp6Address *aMeshLocalAddress,
417 uint16_t aRloc16);
418 void HandleLocateResult(otError aError, const otIp6Address *aMeshLocalAddress, uint16_t aRloc16);
419 #endif
420 #if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
421 static void HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext);
422 void HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo);
423 static void HandleMeshDiagQueryChildTableResult(otError aError,
424 const otMeshDiagChildEntry *aChildEntry,
425 void *aContext);
426 void HandleMeshDiagQueryChildTableResult(otError aError, const otMeshDiagChildEntry *aChildEntry);
427 static void HandleMeshDiagQueryChildIp6Addrs(otError aError,
428 uint16_t aChildRloc16,
429 otMeshDiagIp6AddrIterator *aIp6AddrIterator,
430 void *aContext);
431 void HandleMeshDiagQueryChildIp6Addrs(otError aError,
432 uint16_t aChildRloc16,
433 otMeshDiagIp6AddrIterator *aIp6AddrIterator);
434 static void HandleMeshDiagQueryRouterNeighborTableResult(otError aError,
435 const otMeshDiagRouterNeighborEntry *aNeighborEntry,
436 void *aContext);
437 void HandleMeshDiagQueryRouterNeighborTableResult(otError aError,
438 const otMeshDiagRouterNeighborEntry *aNeighborEntry);
439
440 #endif
441 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
442 static void HandleMlrRegResult(void *aContext,
443 otError aError,
444 uint8_t aMlrStatus,
445 const otIp6Address *aFailedAddresses,
446 uint8_t aFailedAddressNum);
447 void HandleMlrRegResult(otError aError,
448 uint8_t aMlrStatus,
449 const otIp6Address *aFailedAddresses,
450 uint8_t aFailedAddressNum);
451 #endif
452 #if OPENTHREAD_CONFIG_MULTI_RADIO
453 void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo);
454 #endif
455
456 static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
457 static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext);
458 static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
459
460 #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE
461 void HandleDiagnosticGetResponse(otError aError, const otMessage *aMessage, const Ip6::MessageInfo *aMessageInfo);
462 static void HandleDiagnosticGetResponse(otError aError,
463 otMessage *aMessage,
464 const otMessageInfo *aMessageInfo,
465 void *aContext);
466
467 void OutputMode(uint8_t aIndentSize, const otLinkModeConfig &aMode);
468 void OutputConnectivity(uint8_t aIndentSize, const otNetworkDiagConnectivity &aConnectivity);
469 void OutputRoute(uint8_t aIndentSize, const otNetworkDiagRoute &aRoute);
470 void OutputRouteData(uint8_t aIndentSize, const otNetworkDiagRouteData &aRouteData);
471 void OutputLeaderData(uint8_t aIndentSize, const otLeaderData &aLeaderData);
472 void OutputNetworkDiagMacCounters(uint8_t aIndentSize, const otNetworkDiagMacCounters &aMacCounters);
473 void OutputNetworkDiagMleCounters(uint8_t aIndentSize, const otNetworkDiagMleCounters &aMleCounters);
474 void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
475 #endif
476
477 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
478 void OutputTrelCounters(const otTrelCounters &aCounters);
479 #endif
480 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
481 void OutputNat64Counters(const otNat64Counters &aCounters);
482 #endif
483 #if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE
484 void OutputRadioStatsTime(const char *aTimeName, uint64_t aTimeUs, uint64_t aTotalTime);
485 #endif
486
487 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
488 static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult);
489 #endif
490
491 void HandleActiveScanResult(otActiveScanResult *aResult);
492 void HandleEnergyScanResult(otEnergyScanResult *aResult);
493 void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
494 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
495 void HandleSntpResponse(uint64_t aTime, otError aResult);
496 #endif
497
498 static void HandleDetachGracefullyResult(void *aContext);
499 void HandleDetachGracefullyResult(void);
500
501 #if OPENTHREAD_FTD
502 static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext);
503 void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo);
504 #endif
505
506 #if OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK
507 static void HandleIp6Receive(otMessage *aMessage, void *aContext);
508 #endif
509
510 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
511
512 void SetCommandTimeout(uint32_t aTimeoutMilli);
513
514 static void HandleTimer(Timer &aTimer);
515 void HandleTimer(void);
516
517 struct UserCommandsEntry
518 {
519 const otCliCommand *mCommands;
520 uint8_t mLength;
521 void *mContext;
522 };
523
524 UserCommandsEntry mUserCommands[kMaxUserCommandEntries];
525 bool mCommandIsPending;
526 bool mInternalDebugCommand;
527
528 TimerMilliContext mTimer;
529
530 #if OPENTHREAD_FTD || OPENTHREAD_MTD
531 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
532 bool mSntpQueryingInProgress;
533 #endif
534
535 Dataset mDataset;
536 NetworkData mNetworkData;
537 UdpExample mUdp;
538
539 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
540 MacFilter mMacFilter;
541 #endif
542
543 #if OPENTHREAD_CLI_DNS_ENABLE
544 Dns mDns;
545 #endif
546
547 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
548 Bbr mBbr;
549 #endif
550
551 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
552 Br mBr;
553 #endif
554
555 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
556 TcpExample mTcp;
557 #endif
558
559 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
560 Coap mCoap;
561 #endif
562
563 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
564 CoapSecure mCoapSecure;
565 #endif
566
567 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
568 Commissioner mCommissioner;
569 #endif
570
571 #if OPENTHREAD_CONFIG_JOINER_ENABLE
572 Joiner mJoiner;
573 #endif
574
575 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
576 SrpClient mSrpClient;
577 #endif
578
579 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
580 SrpServer mSrpServer;
581 #endif
582
583 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
584 History mHistory;
585 #endif
586 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
587 LinkMetrics mLinkMetrics;
588 #endif
589 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
590 Tcat mTcat;
591 #endif
592 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
593 PingSender mPing;
594 #endif
595 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
596
597 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
598 bool mLocateInProgress : 1;
599 #endif
600 };
601
602 // Specializations of `FormatStringFor<ValueType>()`
603
FormatStringFor(void)604 template <> inline constexpr const char *Interpreter::FormatStringFor<uint8_t>(void) { return "%u"; }
605
FormatStringFor(void)606 template <> inline constexpr const char *Interpreter::FormatStringFor<uint16_t>(void) { return "%u"; }
607
FormatStringFor(void)608 template <> inline constexpr const char *Interpreter::FormatStringFor<uint32_t>(void) { return "%lu"; }
609
FormatStringFor(void)610 template <> inline constexpr const char *Interpreter::FormatStringFor<int8_t>(void) { return "%d"; }
611
FormatStringFor(void)612 template <> inline constexpr const char *Interpreter::FormatStringFor<int16_t>(void) { return "%d"; }
613
FormatStringFor(void)614 template <> inline constexpr const char *Interpreter::FormatStringFor<int32_t>(void) { return "%ld"; }
615
FormatStringFor(void)616 template <> inline constexpr const char *Interpreter::FormatStringFor<const char *>(void) { return "%s"; }
617
618 // Specialization of ProcessGet<> for `uint32_t` and `int32_t`
619
ProcessGet(Arg aArgs[],GetHandler<uint32_t> aGetHandler)620 template <> inline otError Interpreter::ProcessGet<uint32_t>(Arg aArgs[], GetHandler<uint32_t> aGetHandler)
621 {
622 otError error = OT_ERROR_NONE;
623
624 VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
625 OutputLine(FormatStringFor<uint32_t>(), ToUlong(aGetHandler(GetInstancePtr())));
626
627 exit:
628 return error;
629 }
630
ProcessGet(Arg aArgs[],GetHandler<int32_t> aGetHandler)631 template <> inline otError Interpreter::ProcessGet<int32_t>(Arg aArgs[], GetHandler<int32_t> aGetHandler)
632 {
633 otError error = OT_ERROR_NONE;
634
635 VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
636 OutputLine(FormatStringFor<int32_t>(), static_cast<long int>(aGetHandler(GetInstancePtr())));
637
638 exit:
639 return error;
640 }
641
642 } // namespace Cli
643 } // namespace ot
644
645 #endif // CLI_HPP_
646