diff options
author | Tobias Brunner <tobias@strongswan.org> | 2014-01-22 15:29:45 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2014-02-12 14:34:33 +0100 |
commit | 190a27885435f683ecd8e1d0240559ae10229a44 (patch) | |
tree | 8d2862a342a334e2bb31f6e2103044a6a820046a /src/libstrongswan/plugins/plugin_loader.c | |
parent | 79962d9e995b6805c39b0dd3fc3e8d3d974d9abf (diff) | |
download | strongswan-190a27885435f683ecd8e1d0240559ae10229a44.tar.bz2 strongswan-190a27885435f683ecd8e1d0240559ae10229a44.tar.xz |
plugin-loader: Optionally use load option in each plugin section to load plugins
This now works because all plugins use the same config namespace.
If <ns>.load_modular is true, the list of plugins to load is determined
via the value of the <ns>.plugins.<name>.load options.
Using includes the following is possible:
charon {
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
}
}
charon-cmd {
load_modular = yes
plugins {
include strongswan.d/charon-cmd/*.conf
}
}
Where each .conf file would contain something like:
<name> {
load = yes
<option> = <value>
}
To increase the priority of individual plugins load = <priority> can be
used (the default is 1). For instance, to use openssl instead of the
built-in crypto plugins set in strongswan.d/charon/openssl.conf:
openssl {
load = 10
}
If two plugins have the same priority their order in the default plugin
list is preserved. Plugins not found in that list are ordered
alphabetically before other plugins with the same priority.
Diffstat (limited to 'src/libstrongswan/plugins/plugin_loader.c')
-rw-r--r-- | src/libstrongswan/plugins/plugin_loader.c | 139 |
1 files changed, 136 insertions, 3 deletions
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index c9043239b..08a8442ea 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Tobias Brunner + * Copyright (C) 2010-2014 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -28,6 +28,7 @@ #include <utils/debug.h> #include <library.h> #include <collections/hashtable.h> +#include <collections/array.h> #include <collections/linked_list.h> #include <plugins/plugin.h> #include <utils/integrity_checker.h> @@ -936,18 +937,146 @@ static bool find_plugin(char *path, char *name, char *buf, char **file) return FALSE; } +/** + * Used to sort plugins by priority + */ +typedef struct { + /* name of the plugin */ + char *name; + /* the plugins priority */ + int prio; + /* default priority */ + int def; +} plugin_priority_t; + +static void plugin_priority_free(const plugin_priority_t *this, int idx, + void *user) +{ + free(this->name); +} + +/** + * Sort plugins and their priority by name + */ +static int plugin_priority_cmp_name(const plugin_priority_t *a, + const plugin_priority_t *b) +{ + return strcmp(a->name, b->name); +} + +/** + * Sort plugins by decreasing priority or default priority then by name + */ +static int plugin_priority_cmp(const plugin_priority_t *a, + const plugin_priority_t *b, void *user) +{ + int diff; + + diff = b->prio - a->prio; + if (!diff) + { /* the same priority, use default order */ + diff = b->def - a->def; + if (!diff) + { /* same default priority (i.e. both were not found in that list) */ + return strcmp(a->name, b->name); + } + } + return diff; +} + + +/** + * Determine the list of plugins to load via load option in each plugin's + * config section. + */ +static char *modular_pluginlist(char *list) +{ + enumerator_t *enumerator; + array_t *given, *final; + plugin_priority_t item, *current, found; + char *plugin, *plugins = NULL; + int i = 0, max_prio; + + if (!lib->settings->get_bool(lib->settings, "%s.load_modular", FALSE, + lib->ns)) + { + return list; + } + + given = array_create(sizeof(plugin_priority_t), 0); + final = array_create(sizeof(plugin_priority_t), 0); + + enumerator = enumerator_create_token(list, " ", " "); + while (enumerator->enumerate(enumerator, &plugin)) + { + item.name = strdup(plugin); + item.prio = i++; + array_insert(given, ARRAY_TAIL, &item); + } + enumerator->destroy(enumerator); + array_sort(given, (void*)plugin_priority_cmp_name, NULL); + /* the maximum priority used for plugins not found in this list */ + max_prio = i + 1; + + enumerator = lib->settings->create_section_enumerator(lib->settings, + "%s.plugins", lib->ns); + while (enumerator->enumerate(enumerator, &plugin)) + { + item.prio = lib->settings->get_int(lib->settings, + "%s.plugins.%s.load", 0, lib->ns, plugin); + if (!item.prio) + { + if (!lib->settings->get_bool(lib->settings, + "%s.plugins.%s.load", FALSE, lib->ns, plugin)) + { + continue; + } + item.prio = 1; + } + item.name = plugin; + item.def = max_prio; + if (array_bsearch(given, &item, (void*)plugin_priority_cmp_name, + &found) != -1) + { + item.def = max_prio - found.prio; + } + array_insert(final, ARRAY_TAIL, &item); + } + enumerator->destroy(enumerator); + array_destroy_function(given, (void*)plugin_priority_free, NULL); + + array_sort(final, (void*)plugin_priority_cmp, NULL); + + enumerator = array_create_enumerator(final); + while (enumerator->enumerate(enumerator, ¤t)) + { + char *prev = plugins; + if (asprintf(&plugins, "%s %s", plugins ?: "", current->name) < 0) + { + plugins = prev; + break; + } + free(prev); + } + enumerator->destroy(enumerator); + array_destroy(final); + return plugins; +} + METHOD(plugin_loader_t, load_plugins, bool, private_plugin_loader_t *this, char *list) { enumerator_t *enumerator; - char *default_path = NULL, *token; + char *default_path = NULL, *plugins, *token; bool critical_failed = FALSE; #ifdef PLUGINDIR default_path = PLUGINDIR; #endif /* PLUGINDIR */ - enumerator = enumerator_create_token(list, " ", " "); + plugins = modular_pluginlist(list); + + enumerator = enumerator_create_token(plugins, " ", " "); while (!critical_failed && enumerator->enumerate(enumerator, &token)) { plugin_entry_t *entry; @@ -1006,6 +1135,10 @@ METHOD(plugin_loader_t, load_plugins, bool, free(this->loaded_plugins); this->loaded_plugins = loaded_plugins_list(this); } + if (plugins != list) + { + free(plugins); + } return !critical_failed; } |