diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index e08b12306..025e97adb 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -17,6 +17,9 @@ #define _GNU_SOURCE #include "plugin_loader.h" +#include +#include +#include #include #include #include @@ -59,6 +62,11 @@ struct private_plugin_loader_t { */ linked_list_t *loaded; + /** + * List of paths to search for plugins + */ + linked_list_t *paths; + /** * List of names of loaded plugins */ @@ -909,17 +917,36 @@ METHOD(plugin_loader_t, add_static_features, void, register_features(this, entry); } +/** + * Tries to find the plugin with the given name in the given path. + */ +static bool find_plugin(char *path, char *name, char *buf, char **file) +{ + struct stat stb; + + if (path && snprintf(buf, PATH_MAX, "%s/libstrongswan-%s.so", + path, name) < PATH_MAX) + { + if (stat(buf, &stb) == 0) + { + *file = buf; + return TRUE; + } + } + return FALSE; +} + METHOD(plugin_loader_t, load_plugins, bool, - private_plugin_loader_t *this, char *path, char *list) + private_plugin_loader_t *this, char *default_path, char *list) { enumerator_t *enumerator; char *token; bool critical_failed = FALSE; #ifdef PLUGINDIR - if (path == NULL) + if (default_path == NULL) { - path = PLUGINDIR; + default_path = PLUGINDIR; } #endif /* PLUGINDIR */ @@ -943,14 +970,14 @@ METHOD(plugin_loader_t, load_plugins, bool, free(token); continue; } - if (path) + if (this->paths) { - if (snprintf(buf, sizeof(buf), "%s/libstrongswan-%s.so", - path, token) >= sizeof(buf)) - { - return FALSE; - } - file = buf; + this->paths->find_first(this->paths, (void*)find_plugin, NULL, + token, buf, &file); + } + if (!file) + { + find_plugin(default_path, token, buf, &file); } entry = load_plugin(this, token, file, critical); if (entry) @@ -1027,6 +1054,16 @@ METHOD(plugin_loader_t, unload, void, memset(&this->stats, 0, sizeof(this->stats)); } +METHOD(plugin_loader_t, add_path, void, + private_plugin_loader_t *this, char *path) +{ + if (!this->paths) + { + this->paths = linked_list_create(); + } + this->paths->insert_last(this->paths, strdupnull(path)); +} + /** * Reload a plugin by name, NULL for all */ @@ -1102,6 +1139,7 @@ METHOD(plugin_loader_t, destroy, void, this->features->destroy(this->features); this->loaded->destroy(this->loaded); this->plugins->destroy(this->plugins); + DESTROY_FUNCTION_IF(this->paths, free); free(this->loaded_plugins); free(this); } @@ -1117,6 +1155,7 @@ plugin_loader_t *plugin_loader_create() .public = { .add_static_features = _add_static_features, .load = _load_plugins, + .add_path = _add_path, .reload = _reload, .unload = _unload, .create_plugin_enumerator = _create_plugin_enumerator, diff --git a/src/libstrongswan/plugins/plugin_loader.h b/src/libstrongswan/plugins/plugin_loader.h index d4f74b923..15496f4c7 100644 --- a/src/libstrongswan/plugins/plugin_loader.h +++ b/src/libstrongswan/plugins/plugin_loader.h @@ -63,12 +63,29 @@ struct plugin_loader_t { * as a critical plugin. If loading a critical plugin fails, plugin loading * is aborted and FALSE is returned. * + * Additional paths can be added with add_path(), these will be searched + * for the plugins first, in the order they were added, then the given path + * or the default follow. + * + * @note Even though this method could be called multiple times this is + * currently not really supported in regards to plugin features and their + * dependencies (in particular soft dependencies). + * * @param path path containing loadable plugins, NULL for default * @param list space separated list of plugins to load * @return TRUE if all critical plugins loaded successfully */ bool (*load)(plugin_loader_t *this, char *path, char *list); + /** + * Add an additional search path for plugins. + * + * These will be searched in the order they were added. + * + * @param path path containing loadable plugins + */ + void (*add_path)(plugin_loader_t *this, char *path); + /** * Reload the configuration of one or multiple plugins. *