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