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/border_agent.h> 44 #include <openthread/cli.h> 45 #include <openthread/dataset.h> 46 #include <openthread/dns_client.h> 47 #include <openthread/instance.h> 48 #include <openthread/ip6.h> 49 #include <openthread/link.h> 50 #include <openthread/logging.h> 51 #include <openthread/mesh_diag.h> 52 #include <openthread/netdata.h> 53 #include <openthread/ping_sender.h> 54 #include <openthread/sntp.h> 55 #include <openthread/tcp.h> 56 #include <openthread/thread.h> 57 #include <openthread/thread_ftd.h> 58 #include <openthread/udp.h> 59 60 #include "cli/cli_bbr.hpp" 61 #include "cli/cli_br.hpp" 62 #include "cli/cli_coap.hpp" 63 #include "cli/cli_coap_secure.hpp" 64 #include "cli/cli_commissioner.hpp" 65 #include "cli/cli_config.h" 66 #include "cli/cli_dataset.hpp" 67 #include "cli/cli_dns.hpp" 68 #include "cli/cli_history.hpp" 69 #include "cli/cli_joiner.hpp" 70 #include "cli/cli_link_metrics.hpp" 71 #include "cli/cli_mac_filter.hpp" 72 #include "cli/cli_mdns.hpp" 73 #include "cli/cli_network_data.hpp" 74 #include "cli/cli_ping.hpp" 75 #include "cli/cli_srp_client.hpp" 76 #include "cli/cli_srp_server.hpp" 77 #include "cli/cli_tcat.hpp" 78 #include "cli/cli_tcp.hpp" 79 #include "cli/cli_udp.hpp" 80 #include "cli/cli_utils.hpp" 81 82 #include "common/array.hpp" 83 #include "common/code_utils.hpp" 84 #include "common/debug.hpp" 85 #include "common/type_traits.hpp" 86 #include "instance/instance.hpp" 87 88 namespace ot { 89 90 /** 91 * @namespace ot::Cli 92 * 93 * @brief 94 * This namespace contains definitions for the CLI interpreter. 95 * 96 */ 97 namespace Cli { 98 99 extern "C" void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list); 100 extern "C" void otCliAppendResult(otError aError); 101 extern "C" void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength); 102 extern "C" void otCliOutputFormat(const char *aFmt, ...); 103 104 /** 105 * Implements the CLI interpreter. 106 * 107 */ 108 class Interpreter : public OutputImplementer, public Utils 109 { 110 #if OPENTHREAD_FTD || OPENTHREAD_MTD 111 friend class Br; 112 friend class Bbr; 113 friend class Commissioner; 114 friend class Dns; 115 friend class Joiner; 116 friend class LinkMetrics; 117 friend class Mdns; 118 friend class NetworkData; 119 friend class PingSender; 120 friend class SrpClient; 121 friend class SrpServer; 122 #endif 123 friend void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list); 124 friend void otCliAppendResult(otError aError); 125 friend void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength); 126 friend void otCliOutputFormat(const char *aFmt, ...); 127 128 public: 129 /** 130 * Constructor 131 * 132 * @param[in] aInstance The OpenThread instance structure. 133 * @param[in] aCallback A callback method called to process CLI output. 134 * @param[in] aContext A user context pointer. 135 */ 136 explicit Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext); 137 138 /** 139 * Returns a reference to the interpreter object. 140 * 141 * @returns A reference to the interpreter object. 142 * 143 */ GetInterpreter(void)144 static Interpreter &GetInterpreter(void) 145 { 146 OT_ASSERT(sInterpreter != nullptr); 147 148 return *sInterpreter; 149 } 150 151 /** 152 * Initializes the Console interpreter. 153 * 154 * @param[in] aInstance The OpenThread instance structure. 155 * @param[in] aCallback A pointer to a callback method. 156 * @param[in] aContext A pointer to a user context. 157 * 158 */ 159 static void Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext); 160 161 /** 162 * Returns whether the interpreter is initialized. 163 * 164 * @returns Whether the interpreter is initialized. 165 * 166 */ IsInitialized(void)167 static bool IsInitialized(void) { return sInterpreter != nullptr; } 168 169 /** 170 * Interprets a CLI command. 171 * 172 * @param[in] aBuf A pointer to a string. 173 * 174 */ 175 void ProcessLine(char *aBuf); 176 177 /** 178 * Adds commands to the user command table. 179 * 180 * @param[in] aCommands A pointer to an array with user commands. 181 * @param[in] aLength @p aUserCommands length. 182 * @param[in] aContext @p aUserCommands length. 183 * 184 * @retval OT_ERROR_NONE Successfully updated command table with commands from @p aCommands. 185 * @retval OT_ERROR_FAILED No available UserCommandsEntry to register requested user commands. 186 */ 187 otError SetUserCommands(const otCliCommand *aCommands, uint8_t aLength, void *aContext); 188 189 protected: 190 static Interpreter *sInterpreter; 191 192 private: 193 static constexpr uint8_t kIndentSize = 4; 194 static constexpr uint16_t kMaxArgs = 32; 195 static constexpr uint16_t kMaxLineLength = OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH; 196 static constexpr uint16_t kMaxUserCommandEntries = OPENTHREAD_CONFIG_CLI_MAX_USER_CMD_ENTRIES; 197 198 static constexpr uint32_t kNetworkDiagnosticTimeoutMsecs = 5000; 199 static constexpr uint32_t kLocateTimeoutMsecs = 2500; 200 201 static constexpr uint16_t kMaxTxtDataSize = OPENTHREAD_CONFIG_CLI_TXT_RECORD_MAX_SIZE; 202 203 using Command = CommandEntry<Interpreter>; 204 205 void OutputPrompt(void); 206 void OutputResult(otError aError); 207 208 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 209 void OutputBorderRouterCounters(void); 210 #endif 211 212 otError ProcessCommand(Arg aArgs[]); 213 214 template <CommandId kCommandId> otError Process(Arg aArgs[]); 215 216 otError ProcessUserCommands(Arg aArgs[]); 217 218 #if OPENTHREAD_FTD || OPENTHREAD_MTD 219 220 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) 221 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 222 otError ProcessBackboneRouterLocal(Arg aArgs[]); 223 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE 224 otError ProcessBackboneRouterMgmtMlr(Arg aArgs[]); 225 void PrintMulticastListenersTable(void); 226 #endif 227 #endif 228 #endif 229 230 #if OPENTHREAD_FTD 231 void OutputEidCacheEntry(const otCacheEntryInfo &aEntry); 232 #endif 233 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE 234 static void HandleLocateResult(void *aContext, 235 otError aError, 236 const otIp6Address *aMeshLocalAddress, 237 uint16_t aRloc16); 238 void HandleLocateResult(otError aError, const otIp6Address *aMeshLocalAddress, uint16_t aRloc16); 239 #endif 240 #if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD 241 static void HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext); 242 void HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo); 243 static void HandleMeshDiagQueryChildTableResult(otError aError, 244 const otMeshDiagChildEntry *aChildEntry, 245 void *aContext); 246 void HandleMeshDiagQueryChildTableResult(otError aError, const otMeshDiagChildEntry *aChildEntry); 247 static void HandleMeshDiagQueryChildIp6Addrs(otError aError, 248 uint16_t aChildRloc16, 249 otMeshDiagIp6AddrIterator *aIp6AddrIterator, 250 void *aContext); 251 void HandleMeshDiagQueryChildIp6Addrs(otError aError, 252 uint16_t aChildRloc16, 253 otMeshDiagIp6AddrIterator *aIp6AddrIterator); 254 static void HandleMeshDiagQueryRouterNeighborTableResult(otError aError, 255 const otMeshDiagRouterNeighborEntry *aNeighborEntry, 256 void *aContext); 257 void HandleMeshDiagQueryRouterNeighborTableResult(otError aError, 258 const otMeshDiagRouterNeighborEntry *aNeighborEntry); 259 260 #endif 261 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 262 static void HandleMlrRegResult(void *aContext, 263 otError aError, 264 uint8_t aMlrStatus, 265 const otIp6Address *aFailedAddresses, 266 uint8_t aFailedAddressNum); 267 void HandleMlrRegResult(otError aError, 268 uint8_t aMlrStatus, 269 const otIp6Address *aFailedAddresses, 270 uint8_t aFailedAddressNum); 271 #endif 272 #if OPENTHREAD_CONFIG_MULTI_RADIO 273 void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo); 274 #endif 275 276 static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext); 277 static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext); 278 static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext); 279 280 #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE 281 void HandleDiagnosticGetResponse(otError aError, const otMessage *aMessage, const Ip6::MessageInfo *aMessageInfo); 282 static void HandleDiagnosticGetResponse(otError aError, 283 otMessage *aMessage, 284 const otMessageInfo *aMessageInfo, 285 void *aContext); 286 287 void OutputMode(uint8_t aIndentSize, const otLinkModeConfig &aMode); 288 void OutputConnectivity(uint8_t aIndentSize, const otNetworkDiagConnectivity &aConnectivity); 289 void OutputRoute(uint8_t aIndentSize, const otNetworkDiagRoute &aRoute); 290 void OutputRouteData(uint8_t aIndentSize, const otNetworkDiagRouteData &aRouteData); 291 void OutputLeaderData(uint8_t aIndentSize, const otLeaderData &aLeaderData); 292 void OutputNetworkDiagMacCounters(uint8_t aIndentSize, const otNetworkDiagMacCounters &aMacCounters); 293 void OutputNetworkDiagMleCounters(uint8_t aIndentSize, const otNetworkDiagMleCounters &aMleCounters); 294 void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry); 295 #endif 296 297 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 298 void OutputTrelCounters(const otTrelCounters &aCounters); 299 #endif 300 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE 301 void OutputNat64Counters(const otNat64Counters &aCounters); 302 #endif 303 #if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE 304 void OutputRadioStatsTime(const char *aTimeName, uint64_t aTimeUs, uint64_t aTotalTime); 305 #endif 306 307 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE 308 static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult); 309 #endif 310 311 void HandleActiveScanResult(otActiveScanResult *aResult); 312 void HandleEnergyScanResult(otEnergyScanResult *aResult); 313 void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx); 314 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE 315 void HandleSntpResponse(uint64_t aTime, otError aResult); 316 #endif 317 318 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 319 void OutputBorderAgentCounters(const otBorderAgentCounters &aCounters); 320 #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE 321 static void HandleBorderAgentEphemeralKeyStateChange(void *aContext); 322 void HandleBorderAgentEphemeralKeyStateChange(void); 323 #endif 324 #endif 325 326 static void HandleDetachGracefullyResult(void *aContext); 327 void HandleDetachGracefullyResult(void); 328 329 #if OPENTHREAD_FTD 330 static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext); 331 void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo); 332 #endif 333 334 #if OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK 335 static void HandleIp6Receive(otMessage *aMessage, void *aContext); 336 #endif 337 338 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD 339 340 #if OPENTHREAD_CONFIG_DIAG_ENABLE 341 static void HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext); 342 void HandleDiagOutput(const char *aFormat, va_list aArguments); 343 #endif 344 345 void SetCommandTimeout(uint32_t aTimeoutMilli); 346 347 static void HandleTimer(Timer &aTimer); 348 void HandleTimer(void); 349 350 struct UserCommandsEntry 351 { 352 const otCliCommand *mCommands; 353 uint8_t mLength; 354 void *mContext; 355 }; 356 357 UserCommandsEntry mUserCommands[kMaxUserCommandEntries]; 358 bool mCommandIsPending; 359 bool mInternalDebugCommand; 360 361 TimerMilliContext mTimer; 362 363 #if OPENTHREAD_FTD || OPENTHREAD_MTD 364 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE 365 bool mSntpQueryingInProgress; 366 #endif 367 368 Dataset mDataset; 369 NetworkData mNetworkData; 370 UdpExample mUdp; 371 372 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 373 MacFilter mMacFilter; 374 #endif 375 376 #if OPENTHREAD_CLI_DNS_ENABLE 377 Dns mDns; 378 #endif 379 380 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE 381 Mdns mMdns; 382 #endif 383 384 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) 385 Bbr mBbr; 386 #endif 387 388 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 389 Br mBr; 390 #endif 391 392 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE 393 TcpExample mTcp; 394 #endif 395 396 #if OPENTHREAD_CONFIG_COAP_API_ENABLE 397 Coap mCoap; 398 #endif 399 400 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE 401 CoapSecure mCoapSecure; 402 #endif 403 404 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD 405 Commissioner mCommissioner; 406 #endif 407 408 #if OPENTHREAD_CONFIG_JOINER_ENABLE 409 Joiner mJoiner; 410 #endif 411 412 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 413 SrpClient mSrpClient; 414 #endif 415 416 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 417 SrpServer mSrpServer; 418 #endif 419 420 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 421 History mHistory; 422 #endif 423 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 424 LinkMetrics mLinkMetrics; 425 #endif 426 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE 427 Tcat mTcat; 428 #endif 429 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE 430 PingSender mPing; 431 #endif 432 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD 433 434 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE 435 bool mLocateInProgress : 1; 436 #endif 437 }; 438 439 } // namespace Cli 440 } // namespace ot 441 442 #endif // CLI_HPP_ 443