1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301 USA.
18 * Copyright 2008 Novell, Inc.
19 * Copyright 2008 - 2010 Red Hat, Inc.
20 * Copyright 2015 Red Hat, Inc.
23 #include "nm-default.h"
25 #include "nm-vpn-editor-plugin.h"
27 #include "nm-core-internal.h"
29 static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface);
31 G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT)
34 nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
39 * NMVpnEditorPlugin:name:
41 * Short display name of the VPN plugin.
43 g_object_interface_install_property (iface,
44 g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "",
47 G_PARAM_STATIC_STRINGS));
50 * NMVpnEditorPlugin:description:
52 * Longer description of the VPN plugin.
54 g_object_interface_install_property (iface,
55 g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "",
58 G_PARAM_STATIC_STRINGS));
61 * NMVpnEditorPlugin:service:
63 * D-Bus service name of the plugin's VPN service.
65 g_object_interface_install_property (iface,
66 g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "",
69 G_PARAM_STATIC_STRINGS));
72 /*********************************************************************/
75 * nm_vpn_editor_plugin_load_from_file:
76 * @plugin_filename: The path to the share library to load.
77 * Apply some common heuristics to find the library, such as
78 * appending "so" file ending.
79 * If the path is not an absolute path or no matching module
80 * can be found, lookup inside a directory defined at compile time.
81 * Due to this, @check_file might be called for two different paths.
82 * @check_service: if not-null, check that the loaded plugin advertises
84 * @check_owner: if non-negative, check whether the file is owned
85 * by UID @check_owner or by root. In this case also check that
86 * the file is not writable by anybody else.
87 * @check_file: (scope call): optional callback to validate the file prior to
88 * loading the shared library.
89 * @user_data: user data for @check_file
90 * @error: on failure the error reason.
92 * Load the shared libary @plugin_filename and create a new
93 * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory
96 * Returns: (transfer full): a new plugin instance or %NULL on error.
101 nm_vpn_editor_plugin_load_from_file (const char *plugin_filename,
102 const char *check_service,
104 NMUtilsCheckFilePredicate check_file,
108 GModule *module = NULL;
109 gs_free_error GError *local = NULL;
110 NMVpnEditorPluginFactory factory = NULL;
111 NMVpnEditorPlugin *editor_plugin = NULL;
113 g_return_val_if_fail (plugin_filename && *plugin_filename, NULL);
115 /* _nm_utils_check_module_file() fails with ENOENT if the plugin file
116 * does not exist. That is relevant, because nm-applet checks for that. */
117 if (_nm_utils_check_module_file (plugin_filename,
122 module = g_module_open (plugin_filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
126 g_propagate_error (error, local);
131 NM_VPN_PLUGIN_ERROR_FAILED,
132 _("cannot load plugin %s"), plugin_filename);
136 g_clear_error (&local);
138 if (g_module_symbol (module, "nm_vpn_editor_plugin_factory", (gpointer) &factory)) {
139 gs_free_error GError *factory_error = NULL;
140 gboolean success = FALSE;
142 editor_plugin = factory (&factory_error);
144 g_assert (!editor_plugin || G_IS_OBJECT (editor_plugin));
147 gs_free char *plug_name = NULL, *plug_service = NULL;
149 /* Validate plugin properties */
151 g_object_get (G_OBJECT (editor_plugin),
152 NM_VPN_EDITOR_PLUGIN_NAME, &plug_name,
153 NM_VPN_EDITOR_PLUGIN_SERVICE, &plug_service,
156 if (!plug_name || !*plug_name) {
159 NM_VPN_PLUGIN_ERROR_FAILED,
160 _("cannot load VPN plugin in '%s': missing plugin name"),
161 g_module_name (module));
162 } else if ( check_service
163 && g_strcmp0 (plug_service, check_service) != 0) {
166 NM_VPN_PLUGIN_ERROR_FAILED,
167 _("cannot load VPN plugin in '%s': invalid service name"),
168 g_module_name (module));
171 g_object_set_data_full (G_OBJECT (editor_plugin), "gmodule", module,
172 (GDestroyNotify) g_module_close);
177 g_propagate_error (error, factory_error);
178 factory_error = NULL;
182 NM_VPN_PLUGIN_ERROR_FAILED,
183 _("unknown error initializing plugin %s"), plugin_filename);
188 g_module_close (module);
189 editor_plugin = NULL;
194 NM_VPN_PLUGIN_ERROR_FAILED,
195 _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"),
196 g_module_name (module), g_module_error ());
197 g_module_close (module);
198 editor_plugin = NULL;
201 return editor_plugin;
204 /*********************************************************************/
207 * nm_vpn_editor_plugin_get_editor:
208 * @plugin: the #NMVpnEditorPlugin
209 * @connection: the #NMConnection to be edited
210 * @error: on return, an error or %NULL
212 * Returns: (transfer full): a new #NMVpnEditor or %NULL on error
215 nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
216 NMConnection *connection,
219 g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
221 return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error);
224 NMVpnEditorPluginCapability
225 nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin)
227 g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
229 return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin);
233 * nm_vpn_editor_plugin_import:
234 * @plugin: the #NMVpnEditorPlugin
235 * @path: full path to the file to attempt to read into a new #NMConnection
236 * @error: on return, an error or %NULL
238 * Returns: (transfer full): a new #NMConnection imported from @path, or %NULL
239 * on error or if the file at @path was not recognized by this plugin
242 nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin,
246 g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
248 if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) {
249 g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL);
250 return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error);
255 NM_VPN_PLUGIN_ERROR_FAILED,
256 _("the plugin does not support import capability"));
261 nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin,
263 NMConnection *connection,
266 g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
268 if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) {
269 g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE);
270 return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error);
275 NM_VPN_PLUGIN_ERROR_FAILED,
276 _("the plugin does not support export capability"));
281 nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
282 NMConnection *connection)
284 g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
286 if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename)
287 return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection);