Asterisk - The Open Source Telephony Project  18.5.0
res/ari/cli.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Command line for ARI.
22  * \author David M. Lee, II <[email protected]>
23  */
24 
25 #include "asterisk.h"
26 
27 #include "asterisk/astobj2.h"
28 #include "asterisk/cli.h"
29 #include "asterisk/stasis_app.h"
30 #include "internal.h"
31 
32 static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
33 {
35 
36  switch (cmd) {
37  case CLI_INIT:
38  e->command = "ari show status";
39  e->usage =
40  "Usage: ari show status\n"
41  " Shows all ARI settings\n";
42  return NULL;
43  case CLI_GENERATE:
44  return NULL;
45  default:
46  break;
47  }
48 
49  if (a->argc != 3) {
50  return CLI_SHOWUSAGE;
51  }
52 
54 
55  if (!conf) {
56  ast_cli(a->fd, "Error getting ARI configuration\n");
57  return CLI_FAILURE;
58  }
59 
60  ast_cli(a->fd, "ARI Status:\n");
61  ast_cli(a->fd, "Enabled: %s\n", AST_CLI_YESNO(conf->general->enabled));
62  ast_cli(a->fd, "Output format: ");
63  switch (conf->general->format) {
64  case AST_JSON_COMPACT:
65  ast_cli(a->fd, "compact");
66  break;
67  case AST_JSON_PRETTY:
68  ast_cli(a->fd, "pretty");
69  break;
70  }
71  ast_cli(a->fd, "\n");
72  ast_cli(a->fd, "Auth realm: %s\n", conf->general->auth_realm);
73  ast_cli(a->fd, "Allowed Origins: %s\n", conf->general->allowed_origins);
74  ast_cli(a->fd, "User count: %d\n", ao2_container_count(conf->users));
75  return CLI_SUCCESS;
76 }
77 
78 static int show_users_cb(void *obj, void *arg, int flags)
79 {
80  struct ast_ari_conf_user *user = obj;
81  struct ast_cli_args *a = arg;
82 
83  ast_cli(a->fd, "%-4s %s\n",
84  AST_CLI_YESNO(user->read_only),
85  user->username);
86  return 0;
87 }
88 
89 static char *ari_show_users(struct ast_cli_entry *e, int cmd,
90  struct ast_cli_args *a)
91 {
93 
94  switch (cmd) {
95  case CLI_INIT:
96  e->command = "ari show users";
97  e->usage =
98  "Usage: ari show users\n"
99  " Shows all ARI users\n";
100  return NULL;
101  case CLI_GENERATE:
102  return NULL;
103  default:
104  break;
105  }
106 
107  if (a->argc != 3) {
108  return CLI_SHOWUSAGE;
109  }
110 
112  if (!conf) {
113  ast_cli(a->fd, "Error getting ARI configuration\n");
114  return CLI_FAILURE;
115  }
116 
117  ast_cli(a->fd, "r/o? Username\n");
118  ast_cli(a->fd, "---- --------\n");
119 
121 
122  return CLI_SUCCESS;
123 }
124 
126  /*! Nth user to search for */
127  int state;
128  /*! Which user currently on */
129  int which;
130 };
131 
132 static int complete_ari_user_search(void *obj, void *arg, void *data, int flags)
133 {
134  struct user_complete *search = data;
135 
136  if (++search->which > search->state) {
137  return CMP_MATCH;
138  }
139  return 0;
140 }
141 
142 static char *complete_ari_user(struct ast_cli_args *a)
143 {
146 
147  struct user_complete search = {
148  .state = a->n,
149  };
150 
152  if (!conf) {
153  ast_cli(a->fd, "Error getting ARI configuration\n");
154  return CLI_FAILURE;
155  }
156 
157  user = ao2_callback_data(conf->users,
159  complete_ari_user_search, (char*)a->word, &search);
160 
161  return user ? ast_strdup(user->username) : NULL;
162 }
163 
164 static char *complete_ari_show_user(struct ast_cli_args *a)
165 {
166  if (a->pos == 3) {
167  return complete_ari_user(a);
168  }
169 
170  return NULL;
171 }
172 
173 static char *ari_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
174 {
177 
178  switch (cmd) {
179  case CLI_INIT:
180  e->command = "ari show user";
181  e->usage =
182  "Usage: ari show user <username>\n"
183  " Shows a specific ARI user\n";
184  return NULL;
185  case CLI_GENERATE:
186  return complete_ari_show_user(a);
187  default:
188  break;
189  }
190 
191  if (a->argc != 4) {
192  return CLI_SHOWUSAGE;
193  }
194 
196 
197  if (!conf) {
198  ast_cli(a->fd, "Error getting ARI configuration\n");
199  return CLI_FAILURE;
200  }
201 
202  user = ao2_find(conf->users, a->argv[3], OBJ_KEY);
203  if (!user) {
204  ast_cli(a->fd, "User '%s' not found\n", a->argv[3]);
205  return CLI_SUCCESS;
206  }
207 
208  ast_cli(a->fd, "Username: %s\n", user->username);
209  ast_cli(a->fd, "Read only?: %s\n", AST_CLI_YESNO(user->read_only));
210 
211  return CLI_SUCCESS;
212 }
213 
214 static char *ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
215 {
216  RAII_VAR(char *, crypted, NULL, ast_free);
217 
218  switch (cmd) {
219  case CLI_INIT:
220  e->command = "ari mkpasswd";
221  e->usage =
222  "Usage: ari mkpasswd <password>\n"
223  " Encrypts a password for use in ari.conf\n"
224  " Be aware that the password will be shown in the\n"
225  " command line history. The mkpasswd shell command\n"
226  " may be preferable.\n"
227  ;
228  return NULL;
229  case CLI_GENERATE:
230  return NULL;
231  default:
232  break;
233  }
234 
235  if (a->argc != 3) {
236  return CLI_SHOWUSAGE;
237  }
238 
239  crypted = ast_crypt_encrypt(a->argv[2]);
240  if (!crypted) {
241  ast_cli(a->fd, "Failed to encrypt password\n");
242  return CLI_FAILURE;
243  }
244 
245  ast_cli(a->fd,
246  "; Copy the following two lines into ari.conf\n");
247  ast_cli(a->fd, "password_format = crypt\n");
248  ast_cli(a->fd, "password = %s\n", crypted);
249 
250  return CLI_SUCCESS;
251 }
252 
253 static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
254 {
255  struct ao2_container *apps;
256  struct ao2_iterator it_apps;
257  char *app;
258 
259  switch (cmd) {
260  case CLI_INIT:
261  e->command = "ari show apps";
262  e->usage =
263  "Usage: ari show apps\n"
264  " Lists all registered applications.\n"
265  ;
266  return NULL;
267  case CLI_GENERATE:
268  return NULL;
269  default:
270  break;
271  }
272 
273  if (a->argc != 3) {
274  return CLI_SHOWUSAGE;
275  }
276 
277  apps = stasis_app_get_all();
278  if (!apps) {
279  ast_cli(a->fd, "Unable to retrieve registered applications!\n");
280  return CLI_FAILURE;
281  }
282 
283  ast_cli(a->fd, "Application Name \n");
284  ast_cli(a->fd, "=========================\n");
285  it_apps = ao2_iterator_init(apps, 0);
286  while ((app = ao2_iterator_next(&it_apps))) {
287  ast_cli(a->fd, "%-25.25s\n", app);
288  ao2_ref(app, -1);
289  }
290 
291  ao2_iterator_destroy(&it_apps);
292  ao2_ref(apps, -1);
293 
294  return CLI_SUCCESS;
295 }
296 
297 struct app_complete {
298  /*! Nth app to search for */
299  int state;
300  /*! Which app currently on */
301  int which;
302 };
303 
304 static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
305 {
306  struct app_complete *search = data;
307 
308  if (++search->which > search->state) {
309  return CMP_MATCH;
310  }
311  return 0;
312 }
313 
314 static char *complete_ari_app(struct ast_cli_args *a, int include_all)
315 {
317  RAII_VAR(char *, app, NULL, ao2_cleanup);
318 
319  struct app_complete search = {
320  .state = a->n,
321  };
322 
323  if (a->pos != 3) {
324  return NULL;
325  }
326 
327  if (!apps) {
328  ast_cli(a->fd, "Error getting ARI applications\n");
329  return CLI_FAILURE;
330  }
331 
332  if (include_all && ast_strlen_zero(a->word)) {
333  ast_str_container_add(apps, " all");
334  }
335 
338  complete_ari_app_search, (char*)a->word, &search);
339 
340  return app ? ast_strdup(app) : NULL;
341 }
342 
343 static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
344 {
345  void *app;
346 
347  switch (cmd) {
348  case CLI_INIT:
349  e->command = "ari show app";
350  e->usage =
351  "Usage: ari show app <application>\n"
352  " Provide detailed information about a registered application.\n"
353  ;
354  return NULL;
355  case CLI_GENERATE:
356  return complete_ari_app(a, 0);
357  default:
358  break;
359  }
360 
361  if (a->argc != 4) {
362  return CLI_SHOWUSAGE;
363  }
364 
365  app = stasis_app_get_by_name(a->argv[3]);
366  if (!app) {
367  return CLI_FAILURE;
368  }
369 
370  stasis_app_to_cli(app, a);
371 
372  ao2_ref(app, -1);
373 
374  return CLI_SUCCESS;
375 }
376 
377 static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
378 {
379  void *app;
380  int debug;
381 
382  switch (cmd) {
383  case CLI_INIT:
384  e->command = "ari set debug";
385  e->usage =
386  "Usage: ari set debug <application|all> <on|off>\n"
387  " Enable or disable debugging on a specific application.\n"
388  ;
389  return NULL;
390  case CLI_GENERATE:
391  return complete_ari_app(a, 1);
392  default:
393  break;
394  }
395 
396  if (a->argc != 5) {
397  return CLI_SHOWUSAGE;
398  }
399 
400  debug = !strcmp(a->argv[4], "on");
401 
402  if (!strcmp(a->argv[3], "all")) {
404  ast_cli(a->fd, "Debugging on all applications %s\n",
405  debug ? "enabled" : "disabled");
406  return CLI_SUCCESS;
407  }
408 
409  app = stasis_app_get_by_name(a->argv[3]);
410  if (!app) {
411  return CLI_FAILURE;
412  }
413 
414  stasis_app_set_debug(app, debug);
415  ast_cli(a->fd, "Debugging on '%s' %s\n",
416  stasis_app_name(app),
417  debug ? "enabled" : "disabled");
418 
419  ao2_ref(app, -1);
420 
421  return CLI_SUCCESS;
422 }
423 
424 static struct ast_cli_entry cli_ari[] = {
425  AST_CLI_DEFINE(ari_show, "Show ARI settings"),
426  AST_CLI_DEFINE(ari_show_users, "List ARI users"),
427  AST_CLI_DEFINE(ari_show_user, "List single ARI user"),
428  AST_CLI_DEFINE(ari_mkpasswd, "Encrypts a password"),
429  AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
430  AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
431  AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
432 };
433 
435  return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
436 }
437 
439  ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
440 }
static char * ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:377
struct stasis_app * stasis_app_get_by_name(const char *name)
Retrieve a handle to a Stasis application by its name.
Definition: res_stasis.c:1694
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
Registered applications container.
Definition: pbx_app.c:67
struct ast_ari_conf * ast_ari_config_get(void)
Get the current ARI configuration.
#define OBJ_KEY
Definition: astobj2.h:1155
static char * complete_ari_show_user(struct ast_cli_args *a)
Definition: res/ari/cli.c:164
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
static int debug
Global debug status.
Definition: res_xmpp.c:435
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
All configuration options for ARI.
Definition: internal.h:54
static char * ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:32
void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
Dump properties of a stasis_app to the CLI.
Definition: cli.h:152
char * username
Definition: internal.h:98
static int complete_ari_user_search(void *obj, void *arg, void *data, int flags)
Definition: res/ari/cli.c:132
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
static struct apps apps
static char * ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:214
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156
#define ast_strlen_zero(foo)
Definition: strings.h:52
All configuration options for statsd client.
Definition: res_statsd.c:95
static char * ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:253
static struct ast_cli_entry cli_ari[]
Definition: res/ari/cli.c:424
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
const char * stasis_app_name(const struct stasis_app *app)
Retrieve an application&#39;s name.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static char * complete_ari_app(struct ast_cli_args *a, int include_all)
Definition: res/ari/cli.c:314
int ast_ari_cli_register(void)
Register CLI commands for ARI.
Definition: res/ari/cli.c:434
const char *const * argv
Definition: cli.h:161
Per-user configuration options.
Definition: internal.h:96
#define CLI_SHOWUSAGE
Definition: cli.h:45
Internal API&#39;s for res_ari.
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
void stasis_app_set_global_debug(int debug)
Enable/disable request/response and event logging on all applications.
#define CLI_FAILURE
Definition: cli.h:46
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
struct ao2_container * stasis_app_get_all(void)
Gets the names of all registered Stasis applications.
Definition: res_stasis.c:1708
const char * word
Definition: cli.h:163
static char * ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:343
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
structure to hold users read from users.conf
static char * ari_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:173
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static int show_users_cb(void *obj, void *arg, int flags)
Definition: res/ari/cli.c:78
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static char * complete_ari_user(struct ast_cli_args *a)
Definition: res/ari/cli.c:142
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Standard Command Line Interface.
const int pos
Definition: cli.h:164
void ast_ari_cli_unregister(void)
Unregister CLI commands for ARI.
Definition: res/ari/cli.c:438
static char * ari_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res/ari/cli.c:89
void stasis_app_set_debug(struct stasis_app *app, int debug)
Enable/disable request/response and event logging on an application.
Stasis Application API. See Stasis Application API for detailed documentation.
Generic container type.
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
static const char app[]
Definition: app_mysql.c:62
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Definition: strings.c:206
char * ast_crypt_encrypt(const char *key)
Asterisk wrapper around crypt(3) for encrypting passwords.
Definition: crypt.c:190
static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
Definition: res/ari/cli.c:304
static struct test_val a