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