aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/plugins/plugin_loader.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-05-26 13:57:57 +0200
committerTobias Brunner <tobias@strongswan.org>2017-05-26 14:24:13 +0200
commitb668bf3f9ec1e6e44cb31c727ac928105e383b32 (patch)
treedb62e4fcd1a955b5179c6f172a9403500bb24e50 /src/libstrongswan/plugins/plugin_loader.c
parent0da10b73addd8c181bed0772c7eac32d28d8af77 (diff)
parent2e4d110d1e94a3be9da06894832492ff469eec37 (diff)
downloadstrongswan-b668bf3f9ec1.tar.bz2
strongswan-b668bf3f9ec1.tar.xz
Merge branch 'variadic-enumerators'
This adds several changes to enumerator_t and linked_list_t to improve portability. In particular to Apple's ARM64 iOS platform, whose calling convention for variadic and regular functions are different. This means that assigning a non-variadic function to a variadic function pointer, as we did with our enumerator_t::enumerate() implementations and several callbacks, will result in crashes as the called function will access the arguments differently than the caller provided them. To avoid this issue the enumerator_t interface is now fully variadic. A new mandatory method is added, venumerate(), that takes a va_list with the arguments provided while enumerating. enumerate() is replaced with a generic implementation that prepares a va_list and calls the enumerator's venumerate() implementation. As this allows passing the arguments of one enumerator to another it avoids the five pointer hack used by enumerator_create_nested() and enumerator_create_cleaner(). To simplify the implementation of venumerate() a helper macro is provided that assigns values from a given va_list to local variables. The signature of the callback passed to enumerator_create_filter() has also changed significantly. It's now required to enumerate over the original enumerator in the callback as this avoids the previous in/out pointer hack. The arguments to the outer enumerator are provided in a va_list. Similar changes to avoid such five pointer hacks affect the signatures of the callbacks for linked_list_t's invoke_function() and find_first() methods. For the latter the return type also changed from status_t to bool, which is important as SUCCESS is defined as 0, so checks for == SUCCESS will now fail.
Diffstat (limited to 'src/libstrongswan/plugins/plugin_loader.c')
-rw-r--r--src/libstrongswan/plugins/plugin_loader.c118
1 files changed, 70 insertions, 48 deletions
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index 4daf3f13e..42d443b7a 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -465,34 +465,48 @@ static plugin_entry_t *load_plugin(private_plugin_loader_t *this, char *name,
return entry;
}
-/**
- * Convert enumerated provided_feature_t to plugin_feature_t
- */
-static bool feature_filter(void *null, provided_feature_t **provided,
- plugin_feature_t **feature)
+CALLBACK(feature_filter, bool,
+ void *null, enumerator_t *orig, va_list args)
{
- *feature = (*provided)->feature;
- return (*provided)->loaded;
+ provided_feature_t *provided;
+ plugin_feature_t **feature;
+
+ VA_ARGS_VGET(args, feature);
+
+ while (orig->enumerate(orig, &provided))
+ {
+ if (provided->loaded)
+ {
+ *feature = provided->feature;
+ return TRUE;
+ }
+ }
+ return FALSE;
}
-/**
- * Convert enumerated entries to plugin_t
- */
-static bool plugin_filter(void *null, plugin_entry_t **entry, plugin_t **plugin,
- void *in, linked_list_t **list)
+CALLBACK(plugin_filter, bool,
+ void *null, enumerator_t *orig, va_list args)
{
- plugin_entry_t *this = *entry;
+ plugin_entry_t *entry;
+ linked_list_t **list;
+ plugin_t **plugin;
- *plugin = this->plugin;
- if (list)
+ VA_ARGS_VGET(args, plugin, list);
+
+ if (orig->enumerate(orig, &entry))
{
- enumerator_t *features;
- features = enumerator_create_filter(
- this->features->create_enumerator(this->features),
- (void*)feature_filter, NULL, NULL);
- *list = linked_list_create_from_enumerator(features);
+ *plugin = entry->plugin;
+ if (list)
+ {
+ enumerator_t *features;
+ features = enumerator_create_filter(
+ entry->features->create_enumerator(entry->features),
+ feature_filter, NULL, NULL);
+ *list = linked_list_create_from_enumerator(features);
+ }
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
METHOD(plugin_loader_t, create_plugin_enumerator, enumerator_t*,
@@ -500,7 +514,7 @@ METHOD(plugin_loader_t, create_plugin_enumerator, enumerator_t*,
{
return enumerator_create_filter(
this->plugins->create_enumerator(this->plugins),
- (void*)plugin_filter, NULL, NULL);
+ plugin_filter, NULL, NULL);
}
METHOD(plugin_loader_t, has_feature, bool,
@@ -592,18 +606,14 @@ static void load_provided(private_plugin_loader_t *this,
provided_feature_t *provided,
int level);
-/**
- * Used to find a loaded feature
- */
-static bool is_feature_loaded(provided_feature_t *item)
+CALLBACK(is_feature_loaded, bool,
+ provided_feature_t *item, va_list args)
{
return item->loaded;
}
-/**
- * Used to find a loadable feature
- */
-static bool is_feature_loadable(provided_feature_t *item)
+CALLBACK(is_feature_loadable, bool,
+ provided_feature_t *item, va_list args)
{
return !item->loading && !item->loaded && !item->failed;
}
@@ -616,8 +626,7 @@ static bool loaded_feature_matches(registered_feature_t *a,
{
if (plugin_feature_matches(a->feature, b->feature))
{
- return b->plugins->find_first(b->plugins, (void*)is_feature_loaded,
- NULL) == SUCCESS;
+ return b->plugins->find_first(b->plugins, is_feature_loaded, NULL);
}
return FALSE;
}
@@ -630,8 +639,7 @@ static bool loadable_feature_equals(registered_feature_t *a,
{
if (plugin_feature_equals(a->feature, b->feature))
{
- return b->plugins->find_first(b->plugins, (void*)is_feature_loadable,
- NULL) == SUCCESS;
+ return b->plugins->find_first(b->plugins, is_feature_loadable, NULL);
}
return FALSE;
}
@@ -644,8 +652,7 @@ static bool loadable_feature_matches(registered_feature_t *a,
{
if (plugin_feature_matches(a->feature, b->feature))
{
- return b->plugins->find_first(b->plugins, (void*)is_feature_loadable,
- NULL) == SUCCESS;
+ return b->plugins->find_first(b->plugins, is_feature_loadable, NULL);
}
return FALSE;
}
@@ -997,8 +1004,8 @@ static void purge_plugins(private_plugin_loader_t *this)
{ /* feature interface not supported */
continue;
}
- if (entry->features->find_first(entry->features,
- (void*)is_feature_loaded, NULL) != SUCCESS)
+ if (!entry->features->find_first(entry->features, is_feature_loaded,
+ NULL))
{
DBG2(DBG_LIB, "unloading plugin '%s' without loaded features",
entry->plugin->get_name(entry->plugin));
@@ -1048,6 +1055,15 @@ static bool find_plugin(char *path, char *name, char *buf, char **file)
return FALSE;
}
+CALLBACK(find_plugin_cb, bool,
+ char *path, va_list args)
+{
+ char *name, *buf, **file;
+
+ VA_ARGS_VGET(args, name, buf, file);
+ return find_plugin(path, name, buf, file);
+}
+
/**
* Used to sort plugins by priority
*/
@@ -1095,14 +1111,20 @@ static int plugin_priority_cmp(const plugin_priority_t *a,
return diff;
}
-/**
- * Convert enumerated plugin_priority_t to a plugin name
- */
-static bool plugin_priority_filter(void *null, plugin_priority_t **prio,
- char **name)
+CALLBACK(plugin_priority_filter, bool,
+ void *null, enumerator_t *orig, va_list args)
{
- *name = (*prio)->name;
- return TRUE;
+ plugin_priority_t *prio;
+ char **name;
+
+ VA_ARGS_VGET(args, name);
+
+ if (orig->enumerate(orig, &prio))
+ {
+ *name = prio->name;
+ return TRUE;
+ }
+ return FALSE;
}
/**
@@ -1142,7 +1164,7 @@ static char *modular_pluginlist(char *list)
else
{
enumerator = enumerator_create_filter(array_create_enumerator(given),
- (void*)plugin_priority_filter, NULL, NULL);
+ plugin_priority_filter, NULL, NULL);
load_def = TRUE;
}
while (enumerator->enumerate(enumerator, &plugin))
@@ -1224,8 +1246,8 @@ METHOD(plugin_loader_t, load_plugins, bool,
}
if (this->paths)
{
- this->paths->find_first(this->paths, (void*)find_plugin, NULL,
- token, buf, &file);
+ this->paths->find_first(this->paths, find_plugin_cb, NULL, token,
+ buf, &file);
}
if (!file)
{