summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-05-28 22:16:00 +0200
committerThomas Haller <thaller@redhat.com>2015-07-29 22:34:35 +0200
commiteed0d0c58f7f13638eb587e240737048d729cb68 (patch)
tree4a0a0bc21f38f92030b80737f7434fd56230d78c
parentb5cc017ba473de011881e40b26b3ee3433f1567c (diff)
downloadNetworkManager-eed0d0c58f7f13638eb587e240737048d729cb68.tar.gz
libnm: add nm_vpn_editor_plugin_load_from_file() function
-rw-r--r--libnm-core/nm-vpn-editor-plugin.c147
-rw-r--r--libnm-core/nm-vpn-editor-plugin.h10
-rw-r--r--libnm/libnm.ver1
-rw-r--r--po/POTFILES.in1
4 files changed, 159 insertions, 0 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c
index b36b736859..d5fa6d819b 100644
--- a/libnm-core/nm-vpn-editor-plugin.c
+++ b/libnm-core/nm-vpn-editor-plugin.c
@@ -24,6 +24,13 @@
#include "nm-vpn-editor-plugin.h"
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-macros-internal.h"
+#include "gsystem-local-alloc.h"
+#include "nm-core-internal.h"
+
static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface);
G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT)
@@ -67,6 +74,146 @@ nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
G_PARAM_STATIC_STRINGS));
}
+/*********************************************************************/
+
+/**
+ * nm_vpn_editor_plugin_load_from_file:
+ * @plugin_filename: The path to the share library to load.
+ * Apply some common heuristics to find the library, such as
+ * appending "so" file ending.
+ * If the path is not an absolute path or no matching module
+ * can be found, lookup inside a directory defined at compile time.
+ * Due to this, @check_file might be called for two different paths.
+ * @check_name: if not-null, check that the loaded plugin has
+ * the given name.
+ * @check_service: if not-null, check that the loaded plugin advertises
+ * the given service.
+ * @check_owner: if non-negative, check whether the file is owned
+ * by UID @check_owner or by root. In this case also check that
+ * the file is not writable by anybody else.
+ * @check_file: optional callback to validate the file prior to
+ * loading the shared library.
+ * @user_data: user data for @check_file
+ * @error: on failure the error reason.
+ *
+ * Load the shared libary @plugin_filename and create a new
+ * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory
+ * function.
+ *
+ * Returns: (transfer-full): a new plugin instance or %NULL on error.
+ *
+ * Since: 1.2
+ */
+NMVpnEditorPlugin *
+nm_vpn_editor_plugin_load_from_file (const char *plugin_filename,
+ const char *check_name,
+ const char *check_service,
+ int check_owner,
+ NMUtilsCheckFilePredicate check_file,
+ gpointer user_data,
+ GError **error)
+{
+ GModule *module = NULL;
+ gs_free_error GError *local = NULL;
+ NMVpnEditorPluginFactory factory = NULL;
+ NMVpnEditorPlugin *editor_plugin = NULL;
+
+ g_return_val_if_fail (plugin_filename && *plugin_filename, NULL);
+
+ if (g_path_is_absolute (plugin_filename)) {
+ gs_free char *module_filename = NULL;
+
+ module_filename = _nm_utils_check_module_file (plugin_filename,
+ check_owner,
+ check_file,
+ user_data,
+ &local);
+ if (module_filename)
+ module = g_module_open (module_filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ }
+
+ if (!module) {
+ if (local) {
+ g_propagate_error (error, local);
+ local = NULL;
+ } else {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("cannot load plugin %s"), plugin_filename);
+ }
+ return NULL;
+ }
+ g_clear_error (&local);
+
+ if (g_module_symbol (module, "nm_vpn_editor_plugin_factory", (gpointer) &factory)) {
+ gs_free_error GError *factory_error = NULL;
+ gboolean success = FALSE;
+
+ editor_plugin = factory (&factory_error);
+
+ g_assert (!editor_plugin || G_IS_OBJECT (editor_plugin));
+
+ if (editor_plugin) {
+ gs_free char *plug_name = NULL, *plug_service = NULL;
+
+ /* Validate plugin properties */
+
+ g_object_get (G_OBJECT (editor_plugin),
+ NM_VPN_EDITOR_PLUGIN_NAME, &plug_name,
+ NM_VPN_EDITOR_PLUGIN_SERVICE, &plug_service,
+ NULL);
+
+ if (check_name && g_strcmp0 (plug_name, check_name) != 0) {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("cannot load VPN plugin in '%s': invalid plugin name"),
+ g_module_name (module));
+ } else if ( check_service
+ && g_strcmp0 (plug_service, check_service) != 0) {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("cannot load VPN plugin in '%s': invalid service name"),
+ g_module_name (module));
+ } else {
+ /* Success! */
+ g_object_set_data_full (G_OBJECT (editor_plugin), "gmodule", module,
+ (GDestroyNotify) g_module_close);
+ success = TRUE;
+ }
+ } else {
+ if (factory_error) {
+ g_propagate_error (error, factory_error);
+ factory_error = NULL;
+ } else {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("unknown error initializing plugin %s"), plugin_filename);
+ }
+ }
+
+ if (!success) {
+ g_module_close (module);
+ editor_plugin = NULL;
+ }
+ } else {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"),
+ g_module_name (module), g_module_error ());
+ g_module_close (module);
+ editor_plugin = NULL;
+ }
+
+ return editor_plugin;
+}
+
+/*********************************************************************/
+
/**
* nm_vpn_editor_plugin_get_editor:
*
diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h
index a0b1f7aca2..83d765d097 100644
--- a/libnm-core/nm-vpn-editor-plugin.h
+++ b/libnm-core/nm-vpn-editor-plugin.h
@@ -30,6 +30,7 @@
#include <glib-object.h>
#include "nm-connection.h"
+#include "nm-utils.h"
G_BEGIN_DECLS
@@ -138,6 +139,15 @@ gboolean nm_vpn_editor_plugin_export (NMVpnEditorPlugin *pl
char *nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
NMConnection *connection);
+NM_AVAILABLE_IN_1_2
+NMVpnEditorPlugin *nm_vpn_editor_plugin_load_from_file (const char *plugin_filename,
+ const char *check_name,
+ const char *check_service,
+ int check_owner,
+ NMUtilsCheckFilePredicate check_file,
+ gpointer user_data,
+ GError **error);
+
G_END_DECLS
#endif /* __NM_VPN_EDITOR_PLUGIN_H__ */
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 885e063203..43684195e3 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -882,6 +882,7 @@ global:
nm_utils_bond_mode_string_to_int;
nm_utils_enum_from_str;
nm_utils_enum_to_str;
+ nm_vpn_editor_plugin_load_from_file;
nm_vpn_plugin_info_get_filename;
nm_vpn_plugin_info_get_name;
nm_vpn_plugin_info_get_plugin;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4b117109e7..7b2c37ae94 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -77,6 +77,7 @@ libnm-core/nm-setting-wireless-security.c
libnm-core/nm-setting-wireless.c
libnm-core/nm-setting.c
libnm-core/nm-utils.c
+libnm-core/nm-vpn-editor-plugin.c
libnm-core/nm-vpn-plugin-info.c
libnm-glib/nm-device.c
libnm-glib/nm-remote-connection.c