• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2020, 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 implements a simple CLI for the SRP server.
32  */
33 
34 #include "cli_srp_server.hpp"
35 
36 #include <inttypes.h>
37 
38 #include "cli/cli.hpp"
39 #include "common/string.hpp"
40 
41 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
42 
43 namespace ot {
44 namespace Cli {
45 
46 constexpr SrpServer::Command SrpServer::sCommands[];
47 
Process(Arg aArgs[])48 otError SrpServer::Process(Arg aArgs[])
49 {
50     otError        error = OT_ERROR_INVALID_COMMAND;
51     const Command *command;
52 
53     if (aArgs[0].IsEmpty())
54     {
55         IgnoreError(ProcessHelp(aArgs));
56         ExitNow();
57     }
58 
59     command = BinarySearch::Find(aArgs[0].GetCString(), sCommands);
60     VerifyOrExit(command != nullptr);
61 
62     error = (this->*command->mHandler)(aArgs + 1);
63 
64 exit:
65     return error;
66 }
67 
ProcessAddrMode(Arg aArgs[])68 otError SrpServer::ProcessAddrMode(Arg aArgs[])
69 {
70     otError error = OT_ERROR_INVALID_ARGS;
71 
72     if (aArgs[0].IsEmpty())
73     {
74         switch (otSrpServerGetAddressMode(GetInstancePtr()))
75         {
76         case OT_SRP_SERVER_ADDRESS_MODE_UNICAST:
77             OutputLine("unicast");
78             break;
79 
80         case OT_SRP_SERVER_ADDRESS_MODE_ANYCAST:
81             OutputLine("anycast");
82             break;
83         }
84 
85         error = OT_ERROR_NONE;
86     }
87     else if (aArgs[0] == "unicast")
88     {
89         error = otSrpServerSetAddressMode(GetInstancePtr(), OT_SRP_SERVER_ADDRESS_MODE_UNICAST);
90     }
91     else if (aArgs[0] == "anycast")
92     {
93         error = otSrpServerSetAddressMode(GetInstancePtr(), OT_SRP_SERVER_ADDRESS_MODE_ANYCAST);
94     }
95 
96     return error;
97 }
98 
ProcessDomain(Arg aArgs[])99 otError SrpServer::ProcessDomain(Arg aArgs[])
100 {
101     otError error = OT_ERROR_NONE;
102 
103     if (aArgs[0].IsEmpty())
104     {
105         OutputLine("%s", otSrpServerGetDomain(GetInstancePtr()));
106     }
107     else
108     {
109         error = otSrpServerSetDomain(GetInstancePtr(), aArgs[0].GetCString());
110     }
111 
112     return error;
113 }
114 
ProcessState(Arg aArgs[])115 otError SrpServer::ProcessState(Arg aArgs[])
116 {
117     static const char *const kStateStrings[] = {
118         "disabled", // (0) OT_SRP_SERVER_STATE_DISABLED
119         "running",  // (1) OT_SRP_SERVER_STATE_RUNNING
120         "stopped",  // (2) OT_SRP_SERVER_STATE_STOPPED
121     };
122 
123     OT_UNUSED_VARIABLE(aArgs);
124 
125     static_assert(0 == OT_SRP_SERVER_STATE_DISABLED, "OT_SRP_SERVER_STATE_DISABLED value is incorrect");
126     static_assert(1 == OT_SRP_SERVER_STATE_RUNNING, "OT_SRP_SERVER_STATE_RUNNING value is incorrect");
127     static_assert(2 == OT_SRP_SERVER_STATE_STOPPED, "OT_SRP_SERVER_STATE_STOPPED value is incorrect");
128 
129     OutputLine("%s", Stringify(otSrpServerGetState(GetInstancePtr()), kStateStrings));
130 
131     return OT_ERROR_NONE;
132 }
133 
ProcessEnable(Arg aArgs[])134 otError SrpServer::ProcessEnable(Arg aArgs[])
135 {
136     OT_UNUSED_VARIABLE(aArgs);
137 
138     otSrpServerSetEnabled(GetInstancePtr(), /* aEnabled */ true);
139 
140     return OT_ERROR_NONE;
141 }
142 
ProcessDisable(Arg aArgs[])143 otError SrpServer::ProcessDisable(Arg aArgs[])
144 {
145     OT_UNUSED_VARIABLE(aArgs);
146 
147     otSrpServerSetEnabled(GetInstancePtr(), /* aEnabled */ false);
148 
149     return OT_ERROR_NONE;
150 }
151 
ProcessTtl(Arg aArgs[])152 otError SrpServer::ProcessTtl(Arg aArgs[])
153 {
154     otError              error = OT_ERROR_NONE;
155     otSrpServerTtlConfig ttlConfig;
156 
157     if (aArgs[0].IsEmpty())
158     {
159         otSrpServerGetTtlConfig(GetInstancePtr(), &ttlConfig);
160         OutputLine("min ttl: %u", ttlConfig.mMinTtl);
161         OutputLine("max ttl: %u", ttlConfig.mMaxTtl);
162     }
163     else
164     {
165         SuccessOrExit(error = aArgs[0].ParseAsUint32(ttlConfig.mMinTtl));
166         SuccessOrExit(error = aArgs[1].ParseAsUint32(ttlConfig.mMaxTtl));
167         VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
168 
169         error = otSrpServerSetTtlConfig(GetInstancePtr(), &ttlConfig);
170     }
171 
172 exit:
173     return error;
174 }
175 
ProcessLease(Arg aArgs[])176 otError SrpServer::ProcessLease(Arg aArgs[])
177 {
178     otError                error = OT_ERROR_NONE;
179     otSrpServerLeaseConfig leaseConfig;
180 
181     if (aArgs[0].IsEmpty())
182     {
183         otSrpServerGetLeaseConfig(GetInstancePtr(), &leaseConfig);
184         OutputLine("min lease: %u", leaseConfig.mMinLease);
185         OutputLine("max lease: %u", leaseConfig.mMaxLease);
186         OutputLine("min key-lease: %u", leaseConfig.mMinKeyLease);
187         OutputLine("max key-lease: %u", leaseConfig.mMaxKeyLease);
188     }
189     else
190     {
191         SuccessOrExit(error = aArgs[0].ParseAsUint32(leaseConfig.mMinLease));
192         SuccessOrExit(error = aArgs[1].ParseAsUint32(leaseConfig.mMaxLease));
193         SuccessOrExit(error = aArgs[2].ParseAsUint32(leaseConfig.mMinKeyLease));
194         SuccessOrExit(error = aArgs[3].ParseAsUint32(leaseConfig.mMaxKeyLease));
195         VerifyOrExit(aArgs[4].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
196 
197         error = otSrpServerSetLeaseConfig(GetInstancePtr(), &leaseConfig);
198     }
199 
200 exit:
201     return error;
202 }
203 
ProcessHost(Arg aArgs[])204 otError SrpServer::ProcessHost(Arg aArgs[])
205 {
206     otError                error = OT_ERROR_NONE;
207     const otSrpServerHost *host;
208 
209     VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
210 
211     host = nullptr;
212     while ((host = otSrpServerGetNextHost(GetInstancePtr(), host)) != nullptr)
213     {
214         const otIp6Address *addresses;
215         uint8_t             addressesNum;
216         bool                isDeleted = otSrpServerHostIsDeleted(host);
217 
218         OutputLine("%s", otSrpServerHostGetFullName(host));
219         OutputLine(kIndentSize, "deleted: %s", isDeleted ? "true" : "false");
220         if (isDeleted)
221         {
222             continue;
223         }
224 
225         OutputSpaces(kIndentSize);
226         OutputFormat("addresses: [");
227 
228         addresses = otSrpServerHostGetAddresses(host, &addressesNum);
229 
230         for (uint8_t i = 0; i < addressesNum; ++i)
231         {
232             OutputIp6Address(addresses[i]);
233             if (i < addressesNum - 1)
234             {
235                 OutputFormat(", ");
236             }
237         }
238 
239         OutputLine("]");
240     }
241 
242 exit:
243     return error;
244 }
245 
OutputHostAddresses(const otSrpServerHost * aHost)246 void SrpServer::OutputHostAddresses(const otSrpServerHost *aHost)
247 {
248     const otIp6Address *addresses;
249     uint8_t             addressesNum;
250 
251     addresses = otSrpServerHostGetAddresses(aHost, &addressesNum);
252 
253     OutputFormat("[");
254     for (uint8_t i = 0; i < addressesNum; ++i)
255     {
256         if (i != 0)
257         {
258             OutputFormat(", ");
259         }
260 
261         OutputIp6Address(addresses[i]);
262     }
263     OutputFormat("]");
264 }
265 
ProcessService(Arg aArgs[])266 otError SrpServer::ProcessService(Arg aArgs[])
267 {
268     static constexpr char *kAnyServiceName  = nullptr;
269     static constexpr char *kAnyInstanceName = nullptr;
270 
271     otError                error = OT_ERROR_NONE;
272     const otSrpServerHost *host  = nullptr;
273 
274     VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
275 
276     while ((host = otSrpServerGetNextHost(GetInstancePtr(), host)) != nullptr)
277     {
278         const otSrpServerService *service = nullptr;
279 
280         while ((service = otSrpServerHostFindNextService(host, service, OT_SRP_SERVER_FLAGS_BASE_TYPE_SERVICE_ONLY,
281                                                          kAnyServiceName, kAnyInstanceName)) != nullptr)
282         {
283             bool                      isDeleted    = otSrpServerServiceIsDeleted(service);
284             const char *              instanceName = otSrpServerServiceGetInstanceName(service);
285             const otSrpServerService *subService   = nullptr;
286             const uint8_t *           txtData;
287             uint16_t                  txtDataLength;
288             bool                      hasSubType = false;
289 
290             OutputLine("%s", instanceName);
291             OutputLine(kIndentSize, "deleted: %s", isDeleted ? "true" : "false");
292 
293             if (isDeleted)
294             {
295                 continue;
296             }
297 
298             OutputFormat(kIndentSize, "subtypes: ");
299 
300             while ((subService = otSrpServerHostFindNextService(
301                         host, subService, (OT_SRP_SERVER_SERVICE_FLAG_SUB_TYPE | OT_SRP_SERVER_SERVICE_FLAG_ACTIVE),
302                         kAnyServiceName, instanceName)) != nullptr)
303             {
304                 char subLabel[OT_DNS_MAX_LABEL_SIZE];
305 
306                 IgnoreError(otSrpServerServiceGetServiceSubTypeLabel(subService, subLabel, sizeof(subLabel)));
307                 OutputFormat("%s%s", hasSubType ? "," : "", subLabel);
308                 hasSubType = true;
309             }
310 
311             OutputLine(hasSubType ? "" : "(null)");
312 
313             OutputLine(kIndentSize, "port: %hu", otSrpServerServiceGetPort(service));
314             OutputLine(kIndentSize, "priority: %hu", otSrpServerServiceGetPriority(service));
315             OutputLine(kIndentSize, "weight: %hu", otSrpServerServiceGetWeight(service));
316             OutputLine(kIndentSize, "ttl: %hu", otSrpServerServiceGetTtl(service));
317 
318             txtData = otSrpServerServiceGetTxtData(service, &txtDataLength);
319             OutputFormat(kIndentSize, "TXT: ");
320             OutputDnsTxtData(txtData, txtDataLength);
321             OutputLine("");
322 
323             OutputLine(kIndentSize, "host: %s", otSrpServerHostGetFullName(host));
324 
325             OutputFormat(kIndentSize, "addresses: ");
326             OutputHostAddresses(host);
327             OutputLine("");
328         }
329     }
330 
331 exit:
332     return error;
333 }
334 
ProcessSeqNum(Arg aArgs[])335 otError SrpServer::ProcessSeqNum(Arg aArgs[])
336 {
337     otError error = OT_ERROR_NONE;
338 
339     if (aArgs[0].IsEmpty())
340     {
341         OutputLine("%u", otSrpServerGetAnycastModeSequenceNumber(GetInstancePtr()));
342     }
343     else
344     {
345         uint8_t sequenceNumber;
346 
347         SuccessOrExit(error = aArgs[0].ParseAsUint8(sequenceNumber));
348         error = otSrpServerSetAnycastModeSequenceNumber(GetInstancePtr(), sequenceNumber);
349     }
350 
351 exit:
352     return error;
353 }
354 
ProcessHelp(Arg aArgs[])355 otError SrpServer::ProcessHelp(Arg aArgs[])
356 {
357     OT_UNUSED_VARIABLE(aArgs);
358 
359     for (const Command &command : sCommands)
360     {
361         OutputLine(command.mName);
362     }
363 
364     return OT_ERROR_NONE;
365 }
366 
367 } // namespace Cli
368 } // namespace ot
369 
370 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
371