Asterisk - The Open Source Telephony Project  21.4.1
named_acl.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * Jonathan Rose <jrose@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*! \file
21  *
22  * \brief Named Access Control Lists
23  *
24  * \author Jonathan Rose <jrose@digium.com>
25  *
26  * \note Based on a feature proposed by
27  * Olle E. Johansson <oej@edvina.net>
28  */
29 
30 /* This maintains the original "module reload acl" CLI command instead
31  * of replacing it with "module reload named_acl". */
32 #undef AST_MODULE
33 #define AST_MODULE "acl"
34 
35 #include "asterisk.h"
36 
37 #include "asterisk/config.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/module.h"
41 #include "asterisk/cli.h"
42 #include "asterisk/acl.h"
43 #include "asterisk/astobj2.h"
44 #include "asterisk/paths.h"
45 #include "asterisk/stasis.h"
46 #include "asterisk/json.h"
48 
49 #define NACL_CONFIG "acl.conf"
50 #define ACL_FAMILY "acls"
51 
52 /*** DOCUMENTATION
53  <configInfo name="named_acl" language="en_US">
54  <configFile name="named_acl.conf">
55  <configObject name="named_acl">
56  <synopsis>Options for configuring a named ACL</synopsis>
57  <configOption name="permit">
58  <synopsis>An address/subnet from which to allow access</synopsis>
59  </configOption>
60  <configOption name="deny">
61  <synopsis>An address/subnet from which to disallow access</synopsis>
62  </configOption>
63  </configObject>
64  </configFile>
65  </configInfo>
66 ***/
67 
68 /*
69  * Configuration structure - holds pointers to ao2 containers used for configuration
70  * Since there isn't a general level or any other special levels for acl.conf at this
71  * time, it's really a config options friendly wrapper for the named ACL container
72  */
74  struct ao2_container *named_acl_list;
75 };
76 
77 static AO2_GLOBAL_OBJ_STATIC(globals);
78 
79 /*! \note These functions are used for placing/retrieving named ACLs in their ao2_container. */
80 static void *named_acl_config_alloc(void);
81 static void *named_acl_alloc(const char *cat);
82 static void *named_acl_find(struct ao2_container *container, const char *cat);
83 
84 /* Config type for named ACL profiles (must not be named general) */
85 static struct aco_type named_acl_type = {
86  .type = ACO_ITEM, /*!< named_acls are items stored in containers, not individual global objects */
87  .name = "named_acl",
88  .category_match = ACO_BLACKLIST_EXACT,
89  .category = "general", /*!< Match everything but "general" */
90  .item_alloc = named_acl_alloc, /*!< A callback to allocate a new named_acl based on category */
91  .item_find = named_acl_find, /*!< A callback to find a named_acl in some container of named_acls */
92  .item_offset = offsetof(struct named_acl_config, named_acl_list), /*!< Could leave this out since 0 */
93 };
94 
95 /* This array of aco_type structs is necessary to use aco_option_register */
96 struct aco_type *named_acl_types[] = ACO_TYPES(&named_acl_type);
97 
98 struct aco_file named_acl_conf = {
99  .filename = "acl.conf",
100  .types = ACO_TYPES(&named_acl_type),
101 };
102 
103 /* Create a config info struct that describes the config processing for named ACLs. */
104 CONFIG_INFO_CORE("named_acl", cfg_info, globals, named_acl_config_alloc,
105  .files = ACO_FILES(&named_acl_conf),
106 );
107 
108 struct named_acl {
109  struct ast_ha *ha;
110  char name[ACL_NAME_LENGTH]; /* Same max length as a configuration category */
111 };
112 
115 
116 /*! \brief destructor for named_acl_config */
117 static void named_acl_config_destructor(void *obj)
118 {
119  struct named_acl_config *cfg = obj;
120  ao2_cleanup(cfg->named_acl_list);
121 }
122 
123 /*! \brief allocator callback for named_acl_config. Notice it returns void * since it is used by
124  * the backend config code
125  */
126 static void *named_acl_config_alloc(void)
127 {
128  struct named_acl_config *cfg;
129 
130  if (!(cfg = ao2_alloc(sizeof(*cfg), named_acl_config_destructor))) {
131  return NULL;
132  }
133 
134  cfg->named_acl_list = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, 37,
135  named_acl_hash_fn, NULL, named_acl_cmp_fn);
136  if (!cfg->named_acl_list) {
137  goto error;
138  }
139 
140  return cfg;
141 
142 error:
143  ao2_ref(cfg, -1);
144  return NULL;
145 }
146 
147 /*! \brief Destroy a named ACL object */
148 static void destroy_named_acl(void *obj)
149 {
150  struct named_acl *named_acl = obj;
151  ast_free_ha(named_acl->ha);
152 }
153 
154 /*!
155  * \brief Create a named ACL structure
156  *
157  * \param cat name given to the ACL
158  * \retval NULL failure
159  *\retval non-NULL successfully allocated named ACL
160  */
161 static void *named_acl_alloc(const char *cat)
162 {
163  struct named_acl *named_acl;
164 
165  named_acl = ao2_alloc(sizeof(*named_acl), destroy_named_acl);
166  if (!named_acl) {
167  return NULL;
168  }
169 
170  ast_copy_string(named_acl->name, cat, sizeof(named_acl->name));
171 
172  return named_acl;
173 }
174 
175 /*!
176  * \brief Find a named ACL in a container by its name
177  *
178  * \param container ao2container holding the named ACLs
179  * \param cat name of the ACL wanted to be found
180  * \retval pointer to the named ACL if available. Null if not found.
181  */
182 static void *named_acl_find(struct ao2_container *container, const char *cat)
183 {
184  struct named_acl tmp;
185  ast_copy_string(tmp.name, cat, sizeof(tmp.name));
186  return ao2_find(container, &tmp, OBJ_POINTER);
187 }
188 
189 /*!
190  * \internal
191  * \brief Callback function to compare the ACL order of two given categories.
192  * This function is used to sort lists of ACLs received from realtime.
193  *
194  * \param p first category being compared
195  * \param q second category being compared
196  *
197  * \retval -1 (p < q)
198  * \retval 0 (p == q)
199  * \retval 1 (p > q)
200  */
201 static int acl_order_comparator(struct ast_category *p, struct ast_category *q)
202 {
203  int p_value = 0, q_value = 0;
204  struct ast_variable *p_var = ast_category_first(p);
205  struct ast_variable *q_var = ast_category_first(q);
206 
207  while (p_var) {
208  if (!strcasecmp(p_var->name, "rule_order")) {
209  p_value = atoi(p_var->value);
210  break;
211  }
212  p_var = p_var->next;
213  }
214 
215  while (q_var) {
216  if (!strcasecmp(q_var->name, "rule_order")) {
217  q_value = atoi(q_var->value);
218  break;
219  }
220  q_var = q_var->next;
221  }
222 
223  if (p_value < q_value) {
224  return -1;
225  } else if (q_value < p_value) {
226  return 1;
227  }
228 
229  return 0;
230 }
231 
232 /*!
233  * \internal
234  * \brief Search for a named ACL via realtime Database and build the named_acl
235  * if it is valid.
236  *
237  * \param name of the ACL wanted to be found
238  * \retval pointer to the named ACL if available. Null if the ACL subsystem is unconfigured.
239  */
240 static struct named_acl *named_acl_find_realtime(const char *name)
241 {
242  struct ast_config *cfg;
243  char *item = NULL;
244  const char *systemname = NULL;
245  struct ast_ha *built_ha = NULL;
246  struct named_acl *acl;
247 
248  /* If we have a systemname set in the global options, we only want to retrieve entries with a matching systemname field. */
249  systemname = ast_config_AST_SYSTEM_NAME;
250 
251  if (ast_strlen_zero(systemname)) {
252  cfg = ast_load_realtime_multientry(ACL_FAMILY, "name", name, SENTINEL);
253  } else {
254  cfg = ast_load_realtime_multientry(ACL_FAMILY, "name", name, "systemname", systemname, SENTINEL);
255  }
256 
257  if (!cfg) {
258  return NULL;
259  }
260 
261  /* At this point, the configuration must be sorted by the order field. */
262  ast_config_sort_categories(cfg, 0, acl_order_comparator);
263 
264  while ((item = ast_category_browse(cfg, item))) {
265  int append_ha_error = 0;
266  const char *order = ast_variable_retrieve(cfg, item, "rule_order");
267  const char *sense = ast_variable_retrieve(cfg, item, "sense");
268  const char *rule = ast_variable_retrieve(cfg, item, "rule");
269 
270  built_ha = ast_append_ha(sense, rule, built_ha, &append_ha_error);
271  if (append_ha_error) {
272  /* We need to completely reject an ACL that contains any bad rules. */
273  ast_log(LOG_ERROR, "Rejecting realtime ACL due to bad ACL definition '%s': %s - %s - %s\n", name, order, sense, rule);
274  ast_free_ha(built_ha);
275  return NULL;
276  }
277  }
278 
279  ast_config_destroy(cfg);
280 
281  acl = named_acl_alloc(name);
282  if (!acl) {
283  ast_log(LOG_ERROR, "allocation error\n");
284  ast_free_ha(built_ha);
285  return NULL;
286  }
287 
288  acl->ha = built_ha;
289 
290  return acl;
291 }
292 
293 struct ast_ha *ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined)
294 {
295  struct ast_ha *ha = NULL;
296 
297  RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
298  RAII_VAR(struct named_acl *, named_acl, NULL, ao2_cleanup);
299 
300  if (is_realtime) {
301  *is_realtime = 0;
302  }
303 
304  if (is_undefined) {
305  *is_undefined = 0;
306  }
307 
308  /* If the config or its named_acl_list hasn't been initialized, abort immediately. */
309  if ((!cfg) || (!(cfg->named_acl_list))) {
310  ast_log(LOG_ERROR, "Attempted to find named ACL '%s', but the ACL configuration isn't available.\n", name);
311  return NULL;
312  }
313 
314  named_acl = named_acl_find(cfg->named_acl_list, name);
315 
316  /* If a named ACL couldn't be retrieved locally, we need to try realtime storage. */
317  if (!named_acl) {
318  RAII_VAR(struct named_acl *, realtime_acl, NULL, ao2_cleanup);
319 
320  /* Attempt to create from realtime */
321  if ((realtime_acl = named_acl_find_realtime(name))) {
322  if (is_realtime) {
323  *is_realtime = 1;
324  }
325  ha = ast_duplicate_ha_list(realtime_acl->ha);
326  return ha;
327  }
328 
329  /* Couldn't create from realtime. Raise relevant flags and print relevant warnings. */
330  if (ast_realtime_is_mapping_defined(ACL_FAMILY) && !ast_check_realtime(ACL_FAMILY)) {
331  ast_log(LOG_WARNING, "ACL '%s' does not exist. The ACL will be marked as undefined and will automatically fail if applied.\n"
332  "This ACL may exist in the configured realtime backend, but that backend hasn't been registered yet. "
333  "Fix this establishing preload for the backend in 'modules.conf'.\n", name);
334  } else {
335  ast_log(LOG_WARNING, "ACL '%s' does not exist. The ACL will be marked as undefined and will automatically fail if applied.\n", name);
336  }
337 
338  if (is_undefined) {
339  *is_undefined = 1;
340  }
341 
342  return NULL;
343  }
344 
346 
347  if (!ha) {
348  ast_log(LOG_NOTICE, "ACL '%s' contains no rules. It is valid, but it will accept addresses unconditionally.\n", name);
349  }
350 
351  return ha;
352 }
353 
354 /*! \brief Message type for named ACL changes */
356 
357 /*!
358  * \internal
359  * \brief Sends a stasis message corresponding to a given named ACL that has changed or
360  * that all ACLs have been updated and old copies must be refreshed. Consumers of
361  * named ACLs should subscribe to the ast_security_topic and respond to messages
362  * of the ast_named_acl_change_type stasis message type in order to be able to
363  * accommodate changes to named ACLs.
364  *
365  * \param name Name of the ACL that has changed. May be an empty string (but not NULL)
366  * If name is an empty string, then all ACLs must be refreshed.
367  *
368  * \retval 0 success
369  * \retval 1 failure
370  */
371 static int publish_acl_change(const char *name)
372 {
373  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
374  RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
375  RAII_VAR(struct ast_json *, json_object, ast_json_object_create(), ast_json_unref);
376 
377  if (!json_object || !ast_named_acl_change_type()) {
378  goto publish_failure;
379  }
380 
381  if (ast_json_object_set(json_object, "name", ast_json_string_create(name))) {
382  goto publish_failure;
383  }
384 
385  if (!(json_payload = ast_json_payload_create(json_object))) {
386  goto publish_failure;
387  }
388 
389  msg = stasis_message_create(ast_named_acl_change_type(), json_payload);
390 
391  if (!msg) {
392  goto publish_failure;
393  }
394 
396 
397  return 0;
398 
399 publish_failure:
400  ast_log(LOG_ERROR, "Failed to issue ACL change message for %s.\n",
401  ast_strlen_zero(name) ? "all named ACLs" : name);
402  return -1;
403 }
404 
405 /*!
406  * \internal
407  * \brief secondary handler for the 'acl show <name>' command (with arg)
408  *
409  * \param fd file descriptor of the cli
410  * \name name of the ACL requested for display
411  */
412 static void cli_display_named_acl(int fd, const char *name)
413 {
414  int is_realtime = 0;
415 
416  RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
417  RAII_VAR(struct named_acl *, named_acl, NULL, ao2_cleanup);
418 
419  /* If the configuration or the configuration's named_acl_list is unavailable, abort. */
420  if ((!cfg) || (!cfg->named_acl_list)) {
421  ast_log(LOG_ERROR, "Attempted to show named ACL '%s', but the acl configuration isn't available.\n", name);
422  return;
423  }
424 
425  named_acl = named_acl_find(cfg->named_acl_list, name);
426 
427  /* If the named_acl couldn't be found with the search, also abort. */
428  if (!named_acl) {
429  if (!(named_acl = named_acl_find_realtime(name))) {
430  ast_cli(fd, "\nCould not find ACL named '%s'\n", name);
431  return;
432  }
433 
434  is_realtime = 1;
435  }
436 
437  ast_cli(fd, "\nACL: %s%s\n---------------------------------------------\n", name, is_realtime ? " (realtime)" : "");
438  ast_ha_output(fd, named_acl->ha, NULL);
439 }
440 
441 /*!
442  * \internal
443  * \brief secondary handler for the 'acl show' command (no args)
444  *
445  * \param fd file descriptor of the cli
446  */
447 static void cli_display_named_acl_list(int fd)
448 {
449  struct ao2_iterator i;
450  void *o;
451  RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
452 
453  ast_cli(fd, "\nacl\n---\n");
454 
455  if (!cfg || !cfg->named_acl_list) {
456  ast_cli(fd, "ACL configuration isn't available.\n");
457  return;
458  }
459  i = ao2_iterator_init(cfg->named_acl_list, 0);
460 
461  while ((o = ao2_iterator_next(&i))) {
462  struct named_acl *named_acl = o;
463  ast_cli(fd, "%s\n", named_acl->name);
464  ao2_ref(o, -1);
465  }
466 
468 }
469 
470 /*! \brief ACL command show <name> */
471 static char *handle_show_named_acl_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
472 {
473  struct named_acl_config *cfg;
474  int length;
475  struct ao2_iterator i;
476  struct named_acl *named_acl;
477 
478  switch (cmd) {
479  case CLI_INIT:
480  e->command = "acl show";
481  e->usage =
482  "Usage: acl show [name]\n"
483  " Shows a list of named ACLs or lists all entries in a given named ACL.\n";
484  return NULL;
485  case CLI_GENERATE:
486  if (a->pos != 2) {
487  return NULL;
488  }
489 
490  cfg = ao2_global_obj_ref(globals);
491  if (!cfg) {
492  return NULL;
493  }
494  length = strlen(a->word);
495  i = ao2_iterator_init(cfg->named_acl_list, 0);
496  while ((named_acl = ao2_iterator_next(&i))) {
497  if (!strncasecmp(a->word, named_acl->name, length)) {
498  if (ast_cli_completion_add(ast_strdup(named_acl->name))) {
499  ao2_ref(named_acl, -1);
500  break;
501  }
502  }
503  ao2_ref(named_acl, -1);
504  }
506  ao2_ref(cfg, -1);
507 
508  return NULL;
509  }
510 
511  if (a->argc == 2) {
512  cli_display_named_acl_list(a->fd);
513  return CLI_SUCCESS;
514  }
515 
516  if (a->argc == 3) {
517  cli_display_named_acl(a->fd, a->argv[2]);
518  return CLI_SUCCESS;
519  }
520 
521 
522  return CLI_SHOWUSAGE;
523 }
524 
525 static struct ast_cli_entry cli_named_acl[] = {
526  AST_CLI_DEFINE(handle_show_named_acl_cmd, "Show a named ACL or list all named ACLs"),
527 };
528 
529 static int reload_module(void)
530 {
531  enum aco_process_status status;
532 
533  status = aco_process_config(&cfg_info, 1);
534 
535  if (status == ACO_PROCESS_ERROR) {
536  ast_log(LOG_WARNING, "Could not reload ACL config\n");
537  return 0;
538  }
539 
540  if (status == ACO_PROCESS_UNCHANGED) {
541  /* We don't actually log anything if the config was unchanged,
542  * but we don't need to send a config change event either.
543  */
544  return 0;
545  }
546 
547  /* We need to push an ACL change event with no ACL name so that all subscribers update with all ACLs */
548  publish_acl_change("");
549 
550  return 0;
551 }
552 
553 static int unload_module(void)
554 {
555  ast_cli_unregister_multiple(cli_named_acl, ARRAY_LEN(cli_named_acl));
556 
558  aco_info_destroy(&cfg_info);
559  ao2_global_obj_release(globals);
560 
561  return 0;
562 }
563 
564 static int load_module(void)
565 {
566  if (aco_info_init(&cfg_info)) {
568  }
569 
571 
572  /* Register the per level options. */
573  aco_option_register(&cfg_info, "permit", ACO_EXACT, named_acl_types, NULL, OPT_ACL_T, 1, FLDSET(struct named_acl, ha));
574  aco_option_register(&cfg_info, "deny", ACO_EXACT, named_acl_types, NULL, OPT_ACL_T, 0, FLDSET(struct named_acl, ha));
575 
576  aco_process_config(&cfg_info, 0);
577 
578  ast_cli_register_multiple(cli_named_acl, ARRAY_LEN(cli_named_acl));
579 
581 }
582 
583 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Named ACL system",
584  .support_level = AST_MODULE_SUPPORT_CORE,
585  .load = load_module,
586  .unload = unload_module,
587  .reload = reload_module,
588  .load_pri = AST_MODPRI_CORE,
589  .requires = "extconfig",
590 );
struct ast_variable * next
struct ast_ha * ast_duplicate_ha_list(struct ast_ha *original)
Duplicate the contents of a list of host access rules.
Definition: acl.c:276
Security Event Reporting API.
Asterisk main include file. File version handling, generic pbx functions.
AO2_STRING_FIELD_HASH_FN(transport_monitor, key)
Hashing function for struct transport_monitor.
STASIS_MESSAGE_TYPE_DEFN(ast_named_acl_change_type)
Message type for named ACL changes.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
Definition: json.c:756
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
#define OBJ_POINTER
Definition: astobj2.h:1150
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
descriptor for a cli entry.
Definition: cli.h:171
static char * handle_show_named_acl_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
ACL command show
Definition: named_acl.c:471
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3530
Structure for variables, used for configurations and for channel variables.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs ...
AO2_STRING_FIELD_CMP_FN(transport_monitor, key)
Comparison function for struct transport_monitor.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
CONFIG_INFO_CORE("stasis", cfg_info, globals, stasis_config_alloc,.files=ACO_FILES(&stasis_conf),)
Register information about the configs being processed by this module.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
The representation of a single configuration file to be processed.
enum aco_type_t type
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
Utility functions.
static void destroy_named_acl(void *obj)
Destroy a named ACL object.
Definition: named_acl.c:148
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
Configuration File Parser.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
Asterisk JSON abstraction layer.
Asterisk file paths, configured in asterisk.conf.
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
Access Control of various sorts.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_variable * ast_category_first(struct ast_category *cat)
given a pointer to a category, return the root variable.
Definition: main/config.c:1246
aco_process_status
Return values for the aco_process functions.
struct ao2_container * container
Definition: res_fax.c:501
The config had not been edited and no changes applied.
Their was an error and no changes were applied.
Configuration option-handling.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3622
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
static void * named_acl_alloc(const char *cat)
Create a named ACL structure.
Definition: named_acl.c:161
Definition: test_acl.c:111
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
char * command
Definition: cli.h:186
Type for default option handler for ACLs.
Module could not be loaded properly.
Definition: module.h:102
int ast_realtime_is_mapping_defined(const char *family)
Determine if a mapping exists for a given family.
Definition: main/config.c:3193
static void * named_acl_find(struct ao2_container *container, const char *cat)
Find a named ACL in a container by its name.
Definition: named_acl.c:182
const char * usage
Definition: cli.h:177
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
Definition: json.c:399
struct ast_ha * ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined)
Retrieve a named ACL.
Definition: named_acl.c:293
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
void ast_config_sort_categories(struct ast_config *config, int descending, int(*comparator)(struct ast_category *p, struct ast_category *q))
Sorts categories in a config in the order of a numerical value contained within them.
Definition: main/config.c:1260
Standard Command Line Interface.
Type information about a category-level configurable object.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
static void named_acl_config_destructor(void *obj)
destructor for named_acl_config
Definition: named_acl.c:117
const char * filename
void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix)
output an HA to the provided fd
Definition: acl.c:1086
static void * named_acl_config_alloc(void)
allocator callback for named_acl_config. Notice it returns void * since it is used by the backend con...
Definition: named_acl.c:126
Abstract JSON element (object, array, string, int, ...).
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:712
Generic container type.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2761
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
Definition: astobj2.h:847
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#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:941
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.