diff options
Diffstat (limited to 'src/libstrongswan/plugins/plugin_loader.c')
-rw-r--r-- | src/libstrongswan/plugins/plugin_loader.c | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index 3ed30c572..5734c9092 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -17,7 +17,11 @@ #include "plugin_loader.h" +#define _GNU_SOURCE +#include <string.h> #include <dlfcn.h> +#include <limits.h> +#include <stdio.h> #include <debug.h> #include <utils/linked_list.h> @@ -42,68 +46,92 @@ struct private_plugin_loader_t { }; /** - * Implementation of plugin_loader_t.load_plugins. + * load a single plugin */ -static int load(private_plugin_loader_t *this, char *path, char *prefix) +static plugin_t* load_plugin(private_plugin_loader_t *this, + char *path, char *name) { - enumerator_t *enumerator; - char *file, *ending, *rel; + char file[PATH_MAX]; void *handle; - int count = 0; + plugin_t *plugin; + plugin_constructor_t constructor; - enumerator = enumerator_create_directory(path); - if (!enumerator) + snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path, name); + + handle = dlopen(file, RTLD_LAZY); + if (handle == NULL) { - DBG1("opening plugin directory %s failed", path); - return 0; + DBG1("loading plugin '%s' failed: %s", name, dlerror()); + return NULL; } - DBG2("loading plugins from %s", path); - while (enumerator->enumerate(enumerator, &rel, &file, NULL)) + constructor = dlsym(handle, "plugin_create"); + if (constructor == NULL) { - plugin_t *plugin; - plugin_constructor_t constructor; - - ending = file + strlen(file) - 3; - if (ending <= file || !streq(ending, ".so")) - { /* only process .so libraries */ - continue; - } - if (!strneq(prefix, rel, strlen(prefix))) - { - continue; - } - handle = dlopen(file, RTLD_LAZY); - if (handle == NULL) + DBG1("loading plugin '%s' failed: no plugin_create() function", name); + dlclose(handle); + return NULL; + } + plugin = constructor(); + if (plugin == NULL) + { + DBG1("loading plugin '%s' failed: plugin_create() returned NULL", name); + dlclose(handle); + return NULL; + } + DBG2("plugin '%s' loaded successfully", name); + + /* we do not store or free dlopen() handles, leak_detective requires + * the modules to keep loaded until leak report */ + return plugin; +} + +/** + * Implementation of plugin_loader_t.load_plugins. + */ +static int load(private_plugin_loader_t *this, char *path, char *list) +{ + plugin_t *plugin; + char *pos; + int count = 0; + + list = strdupa(list); + while (TRUE) + { + pos = strchr(list, ' '); + if (pos) { - DBG1("loading plugin %s failed: %s", rel, dlerror()); - continue; + *pos = '\0'; } - constructor = dlsym(handle, "plugin_create"); - if (constructor == NULL) - { - DBG1("plugin %s has no plugin_create() function, skipped", rel); - dlclose(handle); - continue; + plugin = load_plugin(this, path, list); + if (plugin) + { /* insert in front to destroy them in reverse order */ + this->plugins->insert_last(this->plugins, plugin); + count++; } - plugin = constructor(); - if (plugin == NULL) + if (!pos) { - DBG1("plugin %s constructor failed, skipping", rel); - dlclose(handle); - continue; + break; } - DBG2("plugin %s loaded successfully", rel); - /* insert in front to destroy them in reverse order */ - this->plugins->insert_last(this->plugins, plugin); - /* we do not store or free dlopen() handles, leak_detective requires - * the modules to keep loaded until leak report */ - count++; + list = pos + 1; } - enumerator->destroy(enumerator); return count; } /** + * Implementation of plugin_loader_t.unload + */ +static void unload(private_plugin_loader_t *this) +{ + plugin_t *plugin; + + while (this->plugins->remove_first(this->plugins, + (void**)&plugin) == SUCCESS) + { + plugin->destroy(plugin); + } +} + +/** * Implementation of plugin_loader_t.destroy */ static void destroy(private_plugin_loader_t *this) @@ -120,6 +148,7 @@ plugin_loader_t *plugin_loader_create() private_plugin_loader_t *this = malloc_thing(private_plugin_loader_t); this->public.load = (int(*)(plugin_loader_t*, char *path, char *prefix))load; + this->public.unload = (void(*)(plugin_loader_t*))unload; this->public.destroy = (void(*)(plugin_loader_t*))destroy; this->plugins = linked_list_create(); |