Coverage Report

Created: 2025-10-28 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openthread/src/cli/cli.hpp
Line
Count
Source
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
     */
142
    static Interpreter &GetInterpreter(void)
143
7.40k
    {
144
7.40k
        OT_ASSERT(sInterpreter != nullptr);
145
146
7.40k
        return *sInterpreter;
147
7.40k
    }
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
     */
163
0
    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 OutputEnhRoute(uint8_t aIndentSize, const otNetworkDiagEnhRoute &aEnhRoute);
266
    void OutputLeaderData(uint8_t aIndentSize, const otLeaderData &aLeaderData);
267
    void OutputIp6AddrList(uint8_t aIndentSize, const otNetworkDiagIp6AddrList &aIp6Addrs);
268
    void OutputNetworkDiagMacCounters(uint8_t aIndentSize, const otNetworkDiagMacCounters &aMacCounters);
269
    void OutputNetworkDiagMleCounters(uint8_t aIndentSize, const otNetworkDiagMleCounters &aMleCounters);
270
    void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
271
#endif
272
273
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
274
    void OutputTrelCounters(const otTrelCounters &aCounters);
275
#endif
276
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
277
    void OutputNat64Counters(const otNat64Counters &aCounters);
278
#endif
279
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE
280
    void OutputRadioStatsTime(const char *aTimeName, uint64_t aTimeUs, uint64_t aTotalTime);
281
#endif
282
283
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
284
    static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult);
285
#endif
286
287
    void HandleActiveScanResult(otActiveScanResult *aResult);
288
    void HandleEnergyScanResult(otEnergyScanResult *aResult);
289
    void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
290
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
291
    void HandleSntpResponse(uint64_t aTime, otError aResult);
292
#endif
293
294
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
295
    void OutputBorderAgentCounters(const otBorderAgentCounters &aCounters);
296
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
297
    static void HandleBorderAgentEphemeralKeyStateChange(void *aContext);
298
    void        HandleBorderAgentEphemeralKeyStateChange(void);
299
#endif
300
#endif
301
302
    static void HandleDetachGracefullyResult(void *aContext);
303
    void        HandleDetachGracefullyResult(void);
304
305
#if OPENTHREAD_FTD
306
    static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext);
307
    void        HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo);
308
#endif
309
310
#if OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK
311
    static void HandleIp6Receive(otMessage *aMessage, void *aContext);
312
#endif
313
314
#if OPENTHREAD_CONFIG_P2P_ENABLE
315
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
316
    static void HandleP2pLinkDone(void *aContext);
317
    void        HandleP2pLinkDone(void);
318
#endif
319
320
    static void HandleP2pUnlinkDone(void *aContext);
321
    void        HandleP2pUnlinkDone(void);
322
#endif
323
324
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
325
    static void HandleWakeupResult(otError aError, void *aContext);
326
    void        HandleWakeupResult(otError aError);
327
#endif
328
329
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
330
331
#if OPENTHREAD_CONFIG_DIAG_ENABLE
332
    static void HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext);
333
    void        HandleDiagOutput(const char *aFormat, va_list aArguments);
334
#endif
335
336
    void SetCommandTimeout(uint32_t aTimeoutMilli);
337
338
    static void HandleTimer(Timer &aTimer);
339
    void        HandleTimer(void);
340
341
    struct UserCommandsEntry
342
    {
343
        const otCliCommand *mCommands;
344
        uint8_t             mLength;
345
        void               *mContext;
346
    };
347
348
    UserCommandsEntry mUserCommands[kMaxUserCommandEntries];
349
    bool              mCommandIsPending;
350
    bool              mInternalDebugCommand;
351
352
    TimerMilliContext mTimer;
353
354
#if OPENTHREAD_FTD || OPENTHREAD_MTD
355
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
356
    bool mSntpQueryingInProgress;
357
#endif
358
359
    Dataset     mDataset;
360
    NetworkData mNetworkData;
361
    UdpExample  mUdp;
362
363
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
364
    MacFilter mMacFilter;
365
#endif
366
367
#if OPENTHREAD_CLI_DNS_ENABLE
368
    Dns mDns;
369
#endif
370
371
#if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE
372
    Mdns mMdns;
373
#endif
374
375
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
376
    Bbr mBbr;
377
#endif
378
379
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
380
    Br mBr;
381
#endif
382
383
#if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
384
    TcpExample mTcp;
385
#endif
386
387
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
388
    Coap mCoap;
389
#endif
390
391
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
392
    CoapSecure mCoapSecure;
393
#endif
394
395
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
396
    Commissioner mCommissioner;
397
#endif
398
399
#if OPENTHREAD_CONFIG_JOINER_ENABLE
400
    Joiner mJoiner;
401
#endif
402
403
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
404
    SrpClient mSrpClient;
405
#endif
406
407
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
408
    SrpServer mSrpServer;
409
#endif
410
411
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
412
    History mHistory;
413
#endif
414
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
415
    LinkMetrics mLinkMetrics;
416
#endif
417
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
418
    Tcat mTcat;
419
#endif
420
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
421
    PingSender mPing;
422
#endif
423
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
424
    MeshDiag mMeshDiag;
425
#endif
426
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
427
428
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
429
    bool mLocateInProgress : 1;
430
#endif
431
};
432
433
} // namespace Cli
434
} // namespace ot
435
436
#endif // CLI_HPP_