summaryrefslogtreecommitdiff
path: root/libnm-core/nm-vpn-editor-plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-vpn-editor-plugin.c')
-rw-r--r--libnm-core/nm-vpn-editor-plugin.c139
1 files changed, 135 insertions, 4 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c
index 5bf72b0cdd..5a2bfa49a0 100644
--- a/libnm-core/nm-vpn-editor-plugin.c
+++ b/libnm-core/nm-vpn-editor-plugin.c
@@ -403,21 +403,152 @@ nm_vpn_editor_plugin_set_editor_library_path (NMVpnEditorPlugin *self,
}
/**
+ * nm_vpn_editor_plugin_get_editor_load:
+ * @self: the #NMVpnEditorPlugin instance
+ * @editor_library_path: (allow-none): the library path to load. If %NULL,
+ * fallback to nm_vpn_editor_plugin_get_editor_library_path().
+ * @connection: the #NMConnection instance passed to the factory method.
+ * @do_file_checks: if %TRUE, check that the file is valid and has proper
+ * permissions before loading the library. Otherwise, the path is passed
+ * directly to dlopen.
+ * @check_owner: if positive, only allow plugins owned by this owner.
+ * This argument is ignored if @do_file_checks is %FALSE.
+ * @check_file: (allow-none): a predicate to test whether the file is valid
+ * before loading the shared library. This argument is ignored if @do_file_checks
+ * is %FALSE.
+ * @user_data: the user-data for @check_file callback.
+ * @load_data: the data passed to the factory method. Currently %NMVpnEditorLoadData
+ * is an opaque type that contains no fields. In the future we might extend this
+ * structure to pass additional arguments to the factory method.
+ * @error: %GError with the error reason
+ *
+ * This loads the shared library from @editor_library_path, optionally performs some checks
+ * on the file before dlopen(), looks up the factory method "nm_vpn_editor_factory"
+ * and calls it to create an NMVpnEditor instance.
+ *
+ * Returns: (transfer-full): a #NMVpnEditor instance of %NULL in case of error.
+ *
+ * Since: 1.4
+ **/
+NMVpnEditor *
+nm_vpn_editor_plugin_get_editor_load (NMVpnEditorPlugin *self,
+ const char *editor_library_path,
+ NMConnection *connection,
+ gboolean do_file_checks,
+ int check_owner,
+ NMUtilsCheckFilePredicate check_file,
+ gpointer user_data,
+ NMVpnEditorLoadData *load_data,
+ GError **error)
+{
+ GModule *module = NULL;
+ NMVpnEditorFactory factory = NULL;
+ NMVpnEditor *editor = NULL;
+ gs_free char *editor_library_path_free = NULL;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (self), NULL);
+
+ if (!editor_library_path) {
+ editor_library_path_free = nm_vpn_editor_plugin_get_editor_library_path (self, TRUE);
+ editor_library_path = editor_library_path_free;
+ } else if (do_file_checks) {
+ editor_library_path_free = _get_editor_library_path_validate_and_absolute (editor_library_path);
+ editor_library_path = editor_library_path_free;
+ }
+
+ if (!editor_library_path) {
+ g_set_error_literal (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("Cannot create VPN editor due to missing editor-library-path"));
+ return NULL;
+ }
+
+ if (do_file_checks) {
+ if (!_nm_utils_check_module_file (editor_library_path,
+ check_owner,
+ check_file,
+ user_data,
+ error))
+ return NULL;
+ }
+
+ module = g_module_open (editor_library_path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ if (!module) {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("cannot load plugin %s"), editor_library_path);
+ return NULL;
+ }
+
+ if (g_module_symbol (module, "nm_vpn_editor_factory", (gpointer) &factory)) {
+ gs_free_error GError *factory_error = NULL;
+
+ editor = factory (self,
+ connection,
+ load_data,
+ &factory_error);
+
+ g_assert (!editor || G_IS_OBJECT (editor));
+
+ if (editor) {
+ g_object_set_data_full (G_OBJECT (editor), "gmodule", module,
+ (GDestroyNotify) g_module_close);
+ } 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 editor plugin %s"), editor_library_path);
+ }
+ g_module_close (module);
+ }
+ } else {
+ g_set_error (error,
+ NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_FAILED,
+ _("failed to load nm_vpn_editor_factory() from %s (%s)"),
+ g_module_name (module), g_module_error ());
+ g_module_close (module);
+ }
+
+ return editor;
+}
+
+/**
* nm_vpn_editor_plugin_get_editor:
- * @plugin: the #NMVpnEditorPlugin
+ * @self: the #NMVpnEditorPlugin
* @connection: the #NMConnection to be edited
* @error: on return, an error or %NULL
*
* Returns: (transfer full): a new #NMVpnEditor or %NULL on error
*/
NMVpnEditor *
-nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
+nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *self,
NMConnection *connection,
GError **error)
{
- g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
+ NMVpnEditorPluginInterface *interface;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (self), NULL);
- return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error);
+ interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (self);
+ if (interface->get_editor)
+ return interface->get_editor (self, connection, error);
+
+ return nm_vpn_editor_plugin_get_editor_load (self,
+ NULL,
+ connection,
+ TRUE,
+ getuid (),
+ NULL,
+ NULL,
+ NULL,
+ error);
}
NMVpnEditorPluginCapability