summaryrefslogtreecommitdiff
path: root/res/res_clialiases.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2014-02-04 02:22:28 +0000
committerJoshua Colp <jcolp@digium.com>2014-02-04 02:22:28 +0000
commit61aa7ce7f73e29194ff3b70268deeb4f89613495 (patch)
tree12eca53980cb60baeeee992d3c7fd52097ae0547 /res/res_clialiases.c
parenta744b29ab5561185929f861744dbdd0af477eabc (diff)
res_clialiases: Fix crash when reloading and re-aliasing an alias that is in use.
The code assumed that unregistering the alias would always succeed while in practice this is not actually true. A common case is the "reload" command itself. If the cli_aliases.conf configuration file was changed and reload executed the command would fail to unregister and ultimately point to freed memory. The reload process now checks whether unregistering succeeded or not and if not the old CLI alias is retained. (closes issue ASTERISK-19773) Reported by: Joel Vandal (closes issue ASTERISK-22757) Reported by: Gareth Blades ........ Merged revisions 407205 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 407210 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 407213 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407217 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_clialiases.c')
-rw-r--r--res/res_clialiases.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/res/res_clialiases.c b/res/res_clialiases.c
index 17a847648..8550b48a5 100644
--- a/res/res_clialiases.c
+++ b/res/res_clialiases.c
@@ -77,15 +77,25 @@ static int alias_cmp_cb(void *obj, void *arg, int flags)
return (alias0->cli_entry.command == alias1->cli_entry.command ? CMP_MATCH | CMP_STOP : 0);
}
-/*! \brief Destruction function used for aliases */
-static void alias_destroy(void *obj)
+/*! \brief Callback for unregistering an alias */
+static int alias_unregister_cb(void *obj, void *arg, int flags)
{
struct cli_alias *alias = obj;
/* Unregister the CLI entry from the core */
ast_cli_unregister(&alias->cli_entry);
- return;
+ /* We can determine if this worked or not by looking at the cli_entry itself */
+ return !alias->cli_entry.command ? CMP_MATCH : 0;
+}
+
+/*! \brief Callback for finding an alias based on name */
+static int alias_name_cb(void *obj, void *arg, int flags)
+{
+ struct cli_alias *alias = obj;
+ char *name = arg;
+
+ return !strcmp(alias->alias, name) ? CMP_MATCH | CMP_STOP : 0;
}
/*! \brief Function which passes through an aliased CLI command to the real one */
@@ -197,7 +207,7 @@ static void load_config(int reload)
/* Destroy any existing CLI aliases */
if (reload) {
- ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
+ ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
}
for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
@@ -207,7 +217,16 @@ static void load_config(int reload)
}
/* Read in those there CLI aliases */
for (v1 = ast_variable_browse(cfg, v->value); v1; v1 = v1->next) {
- if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), alias_destroy))) {
+ struct cli_alias *existing = ao2_callback(cli_aliases, 0, alias_name_cb, (char*)v1->name);
+
+ if (existing) {
+ ast_log(LOG_WARNING, "Alias '%s' could not be unregistered and has been retained\n",
+ existing->alias);
+ ao2_ref(existing, -1);
+ continue;
+ }
+
+ if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), NULL))) {
continue;
}
alias->alias = ((char *) alias) + sizeof(*alias);
@@ -243,6 +262,13 @@ static int reload_module(void)
/*! \brief Function called to unload the module */
static int unload_module(void)
{
+ ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
+
+ if (ao2_container_count(cli_aliases)) {
+ ast_log(LOG_ERROR, "Could not unregister all CLI aliases\n");
+ return -1;
+ }
+
ao2_ref(cli_aliases, -1);
ast_cli_unregister_multiple(cli_alias, ARRAY_LEN(cli_alias));