libnm: merge branch 'th/libnm-vpn-plugin-bgo749877'

- add new NMVpnPluginInfo class with new API to load
  VPN name files.

- move NMVpnEditorPlugin to libnm-core, including code
  to load the client plugin from the shared library.

- deprecate NMVpnPluginOld and add NMVpnServicePlugin.
  The latter is identical to NMVpnPluginOld but renamed
  and introduced as new API for 1.2.

https://bugzilla.gnome.org/show_bug.cgi?id=749877
This commit is contained in:
Thomas Haller 2015-07-29 23:26:52 +02:00
commit 3e39e5b4f0
28 changed files with 3613 additions and 582 deletions

View file

@ -34,142 +34,41 @@
#include <gmodule.h>
#include <glib/gi18n.h>
#include <nm-connection.h>
#include <nm-setting-connection.h>
#include <nm-setting-vpn.h>
#include "nm-glib.h"
#include "vpn-helpers.h"
#define NM_VPN_API_SUBJECT_TO_CHANGE
#include "nm-vpn-plugin-ui-interface.h"
#include "nm-macros-internal.h"
#define VPN_NAME_FILES_DIR SYSCONFDIR"/NetworkManager/VPN"
static gboolean plugins_loaded;
static GSList *plugins = NULL;
static GHashTable *plugins = NULL;
G_DEFINE_QUARK (NMA_ERROR, nma_error)
#define NMA_ERROR nma_error_quark ()
#define NMA_ERROR_GENERIC 0
NMVpnPluginUiInterface *
NMVpnEditorPlugin *
vpn_get_plugin_by_service (const char *service)
{
NMVpnEditorPlugin *plugin = NULL;
NMVpnPluginInfo *plugin_info;
g_return_val_if_fail (service != NULL, NULL);
return g_hash_table_lookup (plugins, service);
if (G_UNLIKELY (!plugins_loaded))
vpn_get_plugins ();
plugin_info = nm_vpn_plugin_info_list_find_by_service (plugins, service);
if (plugin_info) {
plugin = nm_vpn_plugin_info_get_editor_plugin (plugin_info);
if (!plugin)
plugin = nm_vpn_plugin_info_load_editor_plugin (plugin_info, NULL);
}
return plugin;
}
GHashTable *
vpn_get_plugins (GError **error)
GSList *
vpn_get_plugins ()
{
GDir *dir;
const char *f;
if (error)
g_return_val_if_fail (*error == NULL, NULL);
if (plugins)
if (G_LIKELY (plugins_loaded))
return plugins;
dir = g_dir_open (VPN_NAME_FILES_DIR, 0, NULL);
if (!dir) {
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, "Couldn't read VPN .name files directory " VPN_NAME_FILES_DIR ".");
return NULL;
}
plugins = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free, (GDestroyNotify) g_object_unref);
while ((f = g_dir_read_name (dir))) {
char *path = NULL, *service = NULL;
char *so_path = NULL, *so_name = NULL;
GKeyFile *keyfile = NULL;
GModule *module;
NMVpnPluginUiFactory factory = NULL;
if (!g_str_has_suffix (f, ".name"))
continue;
path = g_strdup_printf ("%s/%s", VPN_NAME_FILES_DIR, f);
keyfile = g_key_file_new ();
if (!g_key_file_load_from_file (keyfile, path, 0, NULL))
goto next;
service = g_key_file_get_string (keyfile, "VPN Connection", "service", NULL);
if (!service)
goto next;
so_path = g_key_file_get_string (keyfile, "GNOME", "properties", NULL);
if (!so_path)
goto next;
/* Remove any path and extension components, then reconstruct path
* to the SO in LIBDIR
*/
so_name = g_path_get_basename (so_path);
g_free (so_path);
so_path = g_strdup_printf ("%s/NetworkManager/%s", LIBDIR, so_name);
g_free (so_name);
module = g_module_open (so_path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
if (!module) {
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, "Cannot load the VPN plugin which provides the "
"service '%s'.", service);
goto next;
}
if (g_module_symbol (module, "nm_vpn_plugin_ui_factory", (gpointer) &factory)) {
NMVpnPluginUiInterface *plugin;
GError *factory_error = NULL;
gboolean success = FALSE;
plugin = factory (&factory_error);
if (plugin) {
char *plug_name = NULL, *plug_service = NULL;
/* Validate plugin properties */
g_object_get (G_OBJECT (plugin),
NM_VPN_PLUGIN_UI_INTERFACE_NAME, &plug_name,
NM_VPN_PLUGIN_UI_INTERFACE_SERVICE, &plug_service,
NULL);
if (!plug_name || !strlen (plug_name)) {
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, "cannot load VPN plugin in '%s': missing plugin name",
g_module_name (module));
} else if (!plug_service || strcmp (plug_service, service)) {
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, "cannot load VPN plugin in '%s': invalid service name",
g_module_name (module));
} else {
/* Success! */
g_object_set_data_full (G_OBJECT (plugin), "gmodule", module,
(GDestroyNotify) g_module_close);
g_hash_table_insert (plugins, g_strdup (service), plugin);
success = TRUE;
}
g_free (plug_name);
g_free (plug_service);
} else {
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, "cannot load VPN plugin in '%s': %s",
g_module_name (module), g_module_error ());
}
if (!success)
g_module_close (module);
} else {
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, "cannot locate nm_vpn_plugin_ui_factory() in '%s': %s",
g_module_name (module), g_module_error ());
g_module_close (module);
}
next:
g_free (so_path);
g_free (service);
g_key_file_free (keyfile);
g_free (path);
}
g_dir_close (dir);
plugins_loaded = TRUE;
plugins = nm_vpn_plugin_info_list_load ();
return plugins;
}
@ -409,7 +308,7 @@ vpn_supports_ipv6 (NMConnection *connection)
{
NMSettingVpn *s_vpn;
const char *service_type;
NMVpnPluginUiInterface *plugin;
NMVpnEditorPlugin *plugin;
guint32 capabilities;
s_vpn = nm_connection_get_setting_vpn (connection);
@ -421,6 +320,6 @@ vpn_supports_ipv6 (NMConnection *connection)
plugin = vpn_get_plugin_by_service (service_type);
g_return_val_if_fail (plugin != NULL, FALSE);
capabilities = nm_vpn_plugin_ui_interface_get_capabilities (plugin);
return (capabilities & NM_VPN_PLUGIN_UI_CAPABILITY_IPV6) != 0;
capabilities = nm_vpn_editor_plugin_get_capabilities (plugin);
return NM_FLAGS_HAS (capabilities, NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6);
}

View file

@ -19,16 +19,13 @@
#ifndef _VPN_HELPERS_H_
#define _VPN_HELPERS_H_
#include <nm-connection.h>
#define NM_VPN_API_SUBJECT_TO_CHANGE
#include <nm-vpn-plugin-ui-interface.h>
#include <NetworkManager.h>
#include "nm-glib.h"
GHashTable *vpn_get_plugins (GError **error);
GSList *vpn_get_plugins (void);
NMVpnPluginUiInterface *vpn_get_plugin_by_service (const char *service);
NMVpnEditorPlugin *vpn_get_plugin_by_service (const char *service);
typedef void (*VpnImportSuccessCallback) (NMConnection *connection, gpointer user_data);
void vpn_import (VpnImportSuccessCallback callback, gpointer user_data);

View file

@ -440,6 +440,7 @@ make install DESTDIR=$RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/conf.d
mkdir -p $RPM_BUILD_ROOT%{nmlibdir}/conf.d
mkdir -p $RPM_BUILD_ROOT%{nmlibdir}/VPN
%{__cp} %{SOURCE2} $RPM_BUILD_ROOT%{nmlibdir}/conf.d/
%{__cp} %{SOURCE3} $RPM_BUILD_ROOT%{nmlibdir}/conf.d/
@ -541,6 +542,7 @@ fi
%dir %{_sysconfdir}/%{name}/conf.d
%dir %{nmlibdir}
%dir %{nmlibdir}/conf.d
%dir %{nmlibdir}/VPN
%{_mandir}/man1/*
%{_mandir}/man5/*
%{_mandir}/man8/*

View file

@ -54,6 +54,7 @@ IGNORE_HFILES= \
nm-types.h \
nm-utils-private.h \
nm-vpn-plugin-old.h \
nm-vpn-service-plugin.h \
nm-core-tests-enum-types.h
# Images to copy into HTML directory.

View file

@ -6,6 +6,8 @@ AM_CPPFLAGS = \
-I${top_srcdir}/include \
-DG_LOG_DOMAIN=\""libnm"\" \
-DLOCALEDIR=\"$(datadir)/locale\" \
-DNMCONFDIR=\"$(nmconfdir)\" \
-DNMLIBDIR=\"$(nmlibdir)\" \
-DNETWORKMANAGER_COMPILATION \
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
$(GLIB_CFLAGS)

View file

@ -42,7 +42,9 @@ libnm_core_headers = \
$(core)/nm-setting.h \
$(core)/nm-simple-connection.h \
$(core)/nm-utils.h \
$(core)/nm-vpn-dbus-interface.h
$(core)/nm-vpn-dbus-interface.h \
$(core)/nm-vpn-editor-plugin.h \
$(core)/nm-vpn-plugin-info.h
libnm_core_private_headers = \
$(core)/crypto.h \
@ -93,5 +95,7 @@ libnm_core_sources = \
$(core)/nm-setting-wireless.c \
$(core)/nm-setting.c \
$(core)/nm-simple-connection.c \
$(core)/nm-utils.c
$(core)/nm-utils.c \
$(core)/nm-vpn-editor-plugin.c \
$(core)/nm-vpn-plugin-info.c

View file

@ -136,6 +136,19 @@ char ** _nm_utils_slist_to_strv (GSList *slist, gboolean deep_copy);
GPtrArray * _nm_utils_strv_to_ptrarray (char **strv);
char ** _nm_utils_ptrarray_to_strv (GPtrArray *ptrarray);
gboolean _nm_utils_check_file (const char *filename,
gint64 check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
struct stat *out_st,
GError **error);
char *_nm_utils_check_module_file (const char *name,
int check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
GError **error);
#define NM_UTILS_UUID_TYPE_LEGACY 0
#define NM_UTILS_UUID_TYPE_VARIANT3 1
@ -187,6 +200,26 @@ gboolean _nm_dbus_error_has_name (GError *error,
/***********************************************************/
gboolean _nm_vpn_plugin_info_check_file (const char *filename,
gboolean check_absolute,
gboolean do_validate_filename,
gint64 check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
GError **error);
const char *_nm_vpn_plugin_info_get_default_dir_etc (void);
const char *_nm_vpn_plugin_info_get_default_dir_lib (void);
const char *_nm_vpn_plugin_info_get_default_dir_user (void);
GSList *_nm_vpn_plugin_info_list_load_dir (const char *dirname,
gboolean do_validate_filename,
gint64 check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data);
/***********************************************************/
typedef struct {
const char *name;
gboolean numeric;
@ -202,4 +235,14 @@ int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option)
/***********************************************************/
typedef struct _NMUtilsStrStrDictKey NMUtilsStrStrDictKey;
guint _nm_utils_strstrdictkey_hash (gconstpointer a);
gboolean _nm_utils_strstrdictkey_equal (gconstpointer a, gconstpointer b);
NMUtilsStrStrDictKey *_nm_utils_strstrdictkey_create (const char *v1, const char *v2);
#define _nm_utils_strstrdictkey_static(v1, v2) \
( (NMUtilsStrStrDictKey *) ("\03" v1 "\0" v2 "") )
/***********************************************************/
#endif

View file

@ -30,6 +30,7 @@
#include <libintl.h>
#include <gmodule.h>
#include <glib/gi18n-lib.h>
#include <sys/stat.h>
#include "nm-glib.h"
#include "nm-utils.h"
@ -2409,6 +2410,160 @@ nm_utils_file_is_pkcs12 (const char *filename)
/**********************************************************************************************/
gboolean
_nm_utils_check_file (const char *filename,
gint64 check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
struct stat *out_st,
GError **error)
{
struct stat st_backup;
if (!out_st)
out_st = &st_backup;
if (stat (filename, out_st) != 0) {
int errsv = errno;
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("failed stat file %s: %s"), filename, strerror (errsv));
return FALSE;
}
/* ignore non-files. */
if (!S_ISREG (out_st->st_mode)) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("not a file (%s)"), filename);
return FALSE;
}
/* with check_owner enabled, check that the file belongs to the
* owner or root. */
if ( check_owner >= 0
&& (out_st->st_uid != 0 && (gint64) out_st->st_uid != check_owner)) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("invalid file owner %d for %s"), out_st->st_uid, filename);
return FALSE;
}
/* with check_owner enabled, check that the file cannot be modified
* by other users (except root). */
if ( check_owner >= 0
&& NM_FLAGS_ANY (out_st->st_mode, S_IWGRP | S_IWOTH | S_ISUID)) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("file permissions for %s"), filename);
return FALSE;
}
if ( check_file
&& !check_file (filename, out_st, user_data, error)) {
if (error && !*error) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("reject %s"), filename);
}
return FALSE;
}
return TRUE;
}
static char *
_resolve_module_file_name (const char *file_name)
{
char *name = NULL;
/* g_module_open() is searching for the exact file to load,
* but it doesn't give us a hook to check file permissions
* and ownership. Reimplement the file name resolution.
*
* Copied from g_module_open(). */
/* check whether we have a readable file right away */
if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
name = g_strdup (file_name);
/* try completing file name with standard library suffix */
if ( !name
&& !g_str_has_suffix (file_name, "." G_MODULE_SUFFIX)) {
name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) {
g_free (name);
name = NULL;
}
}
/* g_module_open() would also try appending ".la". We don't do that
* because we require the user to specify a shared library (directly). */
return name;
}
char *
_nm_utils_check_module_file (const char *name,
int check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
GError **error)
{
gs_free char *name_resolved = NULL;
char *s;
if (!g_path_is_absolute (name)) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("path is not absolute (%s)"), name);
return NULL;
}
name_resolved = _resolve_module_file_name (name);
if (!name_resolved) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("could not resolve plugin path (%s)"), name);
return NULL;
}
if (g_str_has_suffix (name_resolved, ".la")) {
/* g_module_open() treats files that end with .la special.
* We don't want to parse the libtool archive. Just error out. */
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("libtool archives are not supported (%s)"), name_resolved);
return NULL;
}
if (!_nm_utils_check_file (name_resolved,
check_owner,
check_file,
user_data,
NULL,
error)) {
return NULL;
}
s = name_resolved;
name_resolved = NULL;
return s;
}
/**********************************************************************************************/
/**
* nm_utils_file_search_in_paths:
* @progname: the helper program name, like "iptables"
@ -3488,6 +3643,105 @@ nm_utils_bond_mode_string_to_int (const char *mode)
/**********************************************************************************************/
#define STRSTRDICTKEY_V1_SET 0x01
#define STRSTRDICTKEY_V2_SET 0x02
#define STRSTRDICTKEY_ALL_SET 0x03
struct _NMUtilsStrStrDictKey {
char type;
char data[1];
};
guint
_nm_utils_strstrdictkey_hash (gconstpointer a)
{
const NMUtilsStrStrDictKey *k = a;
const signed char *p;
guint32 h = 5381;
if (k) {
if (((int) k->type) & ~STRSTRDICTKEY_ALL_SET)
g_return_val_if_reached (0);
h = (h << 5) + h + k->type;
if (k->type & STRSTRDICTKEY_ALL_SET) {
p = (void *) k->data;
for (; *p != '\0'; p++)
h = (h << 5) + h + *p;
if (k->type == STRSTRDICTKEY_ALL_SET) {
/* the key contains two strings. Continue... */
h = (h << 5) + h + '\0';
for (p++; *p != '\0'; p++)
h = (h << 5) + h + *p;
}
}
}
return h;
}
gboolean
_nm_utils_strstrdictkey_equal (gconstpointer a, gconstpointer b)
{
const NMUtilsStrStrDictKey *k1 = a;
const NMUtilsStrStrDictKey *k2 = b;
if (k1 == k2)
return TRUE;
if (!k1 || !k2)
return FALSE;
if (k1->type != k2->type)
return FALSE;
if (k1->type & STRSTRDICTKEY_ALL_SET) {
if (strcmp (k1->data, k2->data) != 0)
return FALSE;
if (k1->type == STRSTRDICTKEY_ALL_SET) {
gsize l = strlen (k1->data) + 1;
return strcmp (&k1->data[l], &k2->data[l]) == 0;
}
}
return TRUE;
}
NMUtilsStrStrDictKey *
_nm_utils_strstrdictkey_create (const char *v1, const char *v2)
{
char type = 0;
gsize l1 = 0, l2 = 0;
NMUtilsStrStrDictKey *k;
if (!v1 && !v2)
return g_malloc0 (1);
/* we need to distinguish between ("",NULL) and (NULL,"").
* Thus, in @type we encode which strings we have present
* as not-NULL. */
if (v1) {
type |= STRSTRDICTKEY_V1_SET;
l1 = strlen (v1) + 1;
}
if (v2) {
type |= STRSTRDICTKEY_V2_SET;
l2 = strlen (v2) + 1;
}
k = g_malloc (G_STRUCT_OFFSET (NMUtilsStrStrDictKey, data) + l1 + l2);
k->type = type;
if (v1)
memcpy (&k->data[0], v1, l1);
if (v2)
memcpy (&k->data[l1], v2, l2);
return k;
}
/**********************************************************************************************/
/* _nm_utils_ascii_str_to_int64:
*
* A wrapper for g_ascii_strtoll, that checks whether the whole string

View file

@ -128,6 +128,10 @@ gboolean nm_utils_file_is_pkcs12 (const char *filename);
typedef gboolean (*NMUtilsFileSearchInPathsPredicate) (const char *filename, gpointer user_data);
struct stat;
typedef gboolean (*NMUtilsCheckFilePredicate) (const char *filename, const struct stat *stat, gpointer user_data, GError **error);
const char *nm_utils_file_search_in_paths (const char *progname,
const char *try_first,
const char *const *paths,

View file

@ -0,0 +1,284 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2008 Novell, Inc.
* Copyright 2008 - 2010 Red Hat, Inc.
* Copyright 2015 Red Hat, Inc.
*/
#include "config.h"
#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)
static void
nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
{
/* Properties */
/**
* NMVpnEditorPlugin:name:
*
* Short display name of the VPN plugin.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnEditorPlugin:description:
*
* Longer description of the VPN plugin.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnEditorPlugin:service:
*
* D-Bus service name of the plugin's VPN service.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "",
NULL,
G_PARAM_READABLE |
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:
*
* Returns: (transfer full):
*/
NMVpnEditor *
nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error);
}
NMVpnEditorPluginCapability
nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin);
}
/**
* nm_vpn_editor_plugin_import:
*
* Returns: (transfer full):
*/
NMConnection *
nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin,
const char *path,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) {
g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error);
}
return NULL;
}
gboolean
nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin,
const char *path,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) {
g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error);
}
return FALSE;
}
char *
nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
NMConnection *connection)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename)
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection);
return NULL;
}

View file

@ -15,8 +15,8 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2008 - 2014 Red Hat, Inc.
* Copyright 2008 Novell, Inc.
* Copyright 2008 - 2015 Red Hat, Inc.
*/
#ifndef __NM_VPN_EDITOR_PLUGIN_H__
@ -28,7 +28,9 @@
#include <glib.h>
#include <glib-object.h>
#include <nm-types.h>
#include "nm-connection.h"
#include "nm-utils.h"
G_BEGIN_DECLS
@ -137,53 +139,15 @@ gboolean nm_vpn_editor_plugin_export (NMVpnEditorPlugin *pl
char *nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
NMConnection *connection);
/**************************************************/
/* Editor interface */
/**************************************************/
#define NM_TYPE_VPN_EDITOR (nm_vpn_editor_get_type ())
#define NM_VPN_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_EDITOR, NMVpnEditor))
#define NM_IS_VPN_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_EDITOR))
#define NM_VPN_EDITOR_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_EDITOR, NMVpnEditorInterface))
/**
* NMVpnEditorInterface:
* @g_iface: the parent interface
* @get_widget: return the #GtkWidget for the VPN editor's UI
* @placeholder: not currently used
* @update_connection: called to save the user-entered options to the connection
* object. Should return %FALSE and set @error if the current options are
* invalid. @error should contain enough information for the plugin to
* determine which UI widget is invalid at a later point in time. For
* example, creating unique error codes for what error occurred and populating
* the message field of @error with the name of the invalid property.
* @changed: emitted when the value of a UI widget changes. May trigger a
* validity check via @update_connection to write values to the connection.
*
* Interface for editing a specific #NMConnection
*/
typedef struct {
GTypeInterface g_iface;
GObject * (*get_widget) (NMVpnEditor *editor);
void (*placeholder) (void);
gboolean (*update_connection) (NMVpnEditor *editor,
NMConnection *connection,
GError **error);
void (*changed) (NMVpnEditor *editor);
} NMVpnEditorInterface;
GType nm_vpn_editor_get_type (void);
GObject * nm_vpn_editor_get_widget (NMVpnEditor *editor);
gboolean nm_vpn_editor_update_connection (NMVpnEditor *editor,
NMConnection *connection,
GError **error);
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 */
#endif /* __NM_VPN_EDITOR_PLUGIN_H__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,114 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2015 Red Hat, Inc.
*/
#ifndef __NM_VPN_PLUGIN_INFO_H__
#define __NM_VPN_PLUGIN_INFO_H__
#include <glib.h>
#include <glib-object.h>
#include "nm-utils.h"
#include "nm-vpn-editor-plugin.h"
G_BEGIN_DECLS
#define NM_TYPE_VPN_PLUGIN_INFO (nm_vpn_plugin_info_get_type ())
#define NM_VPN_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfo))
#define NM_VPN_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass))
#define NM_IS_VPN_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_PLUGIN_INFO))
#define NM_IS_VPN_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_VPN_PLUGIN_INFO))
#define NM_VPN_PLUGIN_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass))
#define NM_VPN_PLUGIN_INFO_NAME "name"
#define NM_VPN_PLUGIN_INFO_FILENAME "filename"
#define NM_VPN_PLUGIN_INFO_KEYFILE "keyfile"
#define NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION "VPN Connection"
#define NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM "libnm"
#define NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME "GNOME"
typedef struct {
NM_AVAILABLE_IN_1_2
GObject parent;
} NMVpnPluginInfo NM_AVAILABLE_IN_1_2;
typedef struct {
NM_AVAILABLE_IN_1_2
GObjectClass parent;
/*< private >*/
NM_AVAILABLE_IN_1_2
gpointer padding[8];
} NMVpnPluginInfoClass NM_AVAILABLE_IN_1_2;
NM_AVAILABLE_IN_1_2
GType nm_vpn_plugin_info_get_type (void);
NM_AVAILABLE_IN_1_2
NMVpnPluginInfo *nm_vpn_plugin_info_new_from_file (const char *filename,
GError **error);
NM_AVAILABLE_IN_1_2
NMVpnPluginInfo *nm_vpn_plugin_info_new_with_data (const char *filename,
GKeyFile *keyfile,
GError **error);
NM_AVAILABLE_IN_1_2
const char *nm_vpn_plugin_info_get_name (NMVpnPluginInfo *self);
NM_AVAILABLE_IN_1_2
const char *nm_vpn_plugin_info_get_filename (NMVpnPluginInfo *self);
NM_AVAILABLE_IN_1_2
const char *nm_vpn_plugin_info_get_service (NMVpnPluginInfo *self);
NM_AVAILABLE_IN_1_2
const char *nm_vpn_plugin_info_get_plugin (NMVpnPluginInfo *self);
NM_AVAILABLE_IN_1_2
const char *nm_vpn_plugin_info_get_program (NMVpnPluginInfo *self);
NM_AVAILABLE_IN_1_2
const char *nm_vpn_plugin_info_lookup_property (NMVpnPluginInfo *self, const char *group, const char *key);
NM_AVAILABLE_IN_1_2
gboolean nm_vpn_plugin_info_validate_filename (const char *filename);
NM_AVAILABLE_IN_1_2
GSList *nm_vpn_plugin_info_list_load (void);
NM_AVAILABLE_IN_1_2
gboolean nm_vpn_plugin_info_list_add (GSList **list, NMVpnPluginInfo *plugin_info, GError **error);
NM_AVAILABLE_IN_1_2
gboolean nm_vpn_plugin_info_list_remove (GSList **list, NMVpnPluginInfo *plugin_info);
NM_AVAILABLE_IN_1_2
NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_name (GSList *list, const char *name);
NM_AVAILABLE_IN_1_2
NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_filename (GSList *list, const char *filename);
NM_AVAILABLE_IN_1_2
NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_service (GSList *list, const char *service);
NM_AVAILABLE_IN_1_2
NMVpnEditorPlugin *nm_vpn_plugin_info_get_editor_plugin (NMVpnPluginInfo *plugin_info);
NM_AVAILABLE_IN_1_2
void nm_vpn_plugin_info_set_editor_plugin (NMVpnPluginInfo *self,
NMVpnEditorPlugin *plugin);
NM_AVAILABLE_IN_1_2
NMVpnEditorPlugin *nm_vpn_plugin_info_load_editor_plugin (NMVpnPluginInfo *plugin_info,
GError **error);
G_END_DECLS
#endif /* __NM_VPN_PLUGIN_INFO_H__ */

View file

@ -4281,6 +4281,54 @@ test_nm_utils_ascii_str_to_int64 (void)
/******************************************************************************/
static void
test_nm_utils_strstrdictkey ()
{
#define _VALUES_STATIC(_v1, _v2) { .v1 = _v1, .v2 = _v2, .v_static = _nm_utils_strstrdictkey_static (_v1, _v2), }
const struct {
const char *v1;
const char *v2;
NMUtilsStrStrDictKey *v_static;
} *val1, *val2, values[] = {
{ NULL, NULL },
{ "", NULL },
{ NULL, "" },
{ "a", NULL },
{ NULL, "a" },
_VALUES_STATIC ("", ""),
_VALUES_STATIC ("a", ""),
_VALUES_STATIC ("", "a"),
_VALUES_STATIC ("a", "b"),
};
guint i, j;
for (i = 0; i < G_N_ELEMENTS (values); i++) {
gs_free NMUtilsStrStrDictKey *key1 = NULL;
val1 = &values[i];
key1 = _nm_utils_strstrdictkey_create (val1->v1, val1->v2);
if (val1->v_static) {
g_assert (_nm_utils_strstrdictkey_equal (key1, val1->v_static));
g_assert (_nm_utils_strstrdictkey_equal (val1->v_static, key1));
g_assert_cmpint (_nm_utils_strstrdictkey_hash (key1), ==, _nm_utils_strstrdictkey_hash (val1->v_static));
}
for (j = 0; j < G_N_ELEMENTS (values); j++) {
gs_free NMUtilsStrStrDictKey *key2 = NULL;
val2 = &values[j];
key2 = _nm_utils_strstrdictkey_create (val2->v1, val2->v2);
if (i != j) {
g_assert (!_nm_utils_strstrdictkey_equal (key1, key2));
g_assert (!_nm_utils_strstrdictkey_equal (key2, key1));
}
}
}
}
/******************************************************************************/
static void
test_nm_utils_dns_option_validate_do (char *option, gboolean ipv6, const NMUtilsDNSOptionDesc *descs,
gboolean exp_result, char *exp_name, gboolean exp_value)
@ -4764,6 +4812,7 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);

View file

@ -50,12 +50,13 @@ libnminclude_hfiles = \
nm-remote-connection.h \
nm-types.h \
nm-vpn-connection.h \
nm-vpn-editor-plugin.h \
nm-vpn-editor.h \
nm-wimax-nsp.h
libnminclude_nointrospect_hfiles = \
nm-secret-agent-old.h \
nm-vpn-plugin-old.h
nm-vpn-plugin-old.h \
nm-vpn-service-plugin.h
libnminclude_HEADERS = \
$(libnminclude_hfiles) \
@ -108,7 +109,8 @@ libnm_la_csources = \
nm-secret-agent-old.c \
nm-vpn-connection.c \
nm-vpn-plugin-old.c \
nm-vpn-editor-plugin.c \
nm-vpn-editor.c \
nm-vpn-service-plugin.c \
nm-wimax-nsp.c
libnm_la_SOURCES = \

View file

@ -81,7 +81,9 @@
#include <nm-version.h>
#include <nm-vpn-connection.h>
#include <nm-vpn-dbus-interface.h>
#include <nm-vpn-editor.h>
#include <nm-vpn-editor-plugin.h>
#include <nm-vpn-plugin-info.h>
#include <nm-wimax-nsp.h>
#undef __NETWORKMANAGER_H_INSIDE__

View file

@ -821,17 +821,6 @@ global:
nm_vpn_plugin_error_get_type;
nm_vpn_plugin_error_quark;
nm_vpn_plugin_failure_get_type;
nm_vpn_plugin_old_disconnect;
nm_vpn_plugin_old_failure;
nm_vpn_plugin_old_get_connection;
nm_vpn_plugin_old_get_secret_flags;
nm_vpn_plugin_old_get_state;
nm_vpn_plugin_old_get_type;
nm_vpn_plugin_old_read_vpn_details;
nm_vpn_plugin_old_secrets_required;
nm_vpn_plugin_old_set_ip4_config;
nm_vpn_plugin_old_set_login_banner;
nm_vpn_plugin_old_set_state;
nm_vpn_service_state_get_type;
nm_wep_key_type_get_type;
nm_wimax_nsp_connection_valid;
@ -882,4 +871,35 @@ 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_editor_plugin;
nm_vpn_plugin_info_get_name;
nm_vpn_plugin_info_get_plugin;
nm_vpn_plugin_info_get_program;
nm_vpn_plugin_info_get_service;
nm_vpn_plugin_info_get_type;
nm_vpn_plugin_info_load_editor_plugin;
nm_vpn_plugin_info_lookup_property;
nm_vpn_plugin_info_new_from_file;
nm_vpn_plugin_info_new_with_data;
nm_vpn_plugin_info_set_editor_plugin;
nm_vpn_plugin_info_validate_filename;
nm_vpn_plugin_info_list_add;
nm_vpn_plugin_info_list_find_by_filename;
nm_vpn_plugin_info_list_find_by_name;
nm_vpn_plugin_info_list_find_by_service;
nm_vpn_plugin_info_list_load;
nm_vpn_plugin_info_list_remove;
nm_vpn_service_plugin_disconnect;
nm_vpn_service_plugin_failure;
nm_vpn_service_plugin_get_connection;
nm_vpn_service_plugin_get_secret_flags;
nm_vpn_service_plugin_get_state;
nm_vpn_service_plugin_get_type;
nm_vpn_service_plugin_read_vpn_details;
nm_vpn_service_plugin_secrets_required;
nm_vpn_service_plugin_set_ip4_config;
nm_vpn_service_plugin_set_login_banner;
nm_vpn_service_plugin_set_state;
} libnm_1_0_0;

View file

@ -1,181 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2008 - 2010 Red Hat, Inc.
* Copyright 2008 Novell, Inc.
*/
#include "config.h"
#include "nm-vpn-editor-plugin.h"
static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface);
G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT)
static void
nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
{
/* Properties */
/**
* NMVpnEditorPlugin:name:
*
* Short display name of the VPN plugin.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnEditorPlugin:description:
*
* Longer description of the VPN plugin.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnEditorPlugin:service:
*
* D-Bus service name of the plugin's VPN service.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}
/**
* nm_vpn_editor_plugin_get_editor:
*
* Returns: (transfer full):
*/
NMVpnEditor *
nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error);
}
NMVpnEditorPluginCapability
nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin);
}
/**
* nm_vpn_editor_plugin_import:
*
* Returns: (transfer full):
*/
NMConnection *
nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin,
const char *path,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) {
g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error);
}
return NULL;
}
gboolean
nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin,
const char *path,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) {
g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error);
}
return FALSE;
}
char *
nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
NMConnection *connection)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename)
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection);
return NULL;
}
static void nm_vpn_editor_default_init (NMVpnEditorInterface *iface);
G_DEFINE_INTERFACE (NMVpnEditor, nm_vpn_editor, G_TYPE_OBJECT)
static void
nm_vpn_editor_default_init (NMVpnEditorInterface *iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (iface);
/* Signals */
g_signal_new ("changed",
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMVpnEditorInterface, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
/**
* nm_vpn_editor_get_widget:
*
* Returns: (transfer none):
*/
GObject *
nm_vpn_editor_get_widget (NMVpnEditor *editor)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), NULL);
return NM_VPN_EDITOR_GET_INTERFACE (editor)->get_widget (editor);
}
gboolean
nm_vpn_editor_update_connection (NMVpnEditor *editor,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), FALSE);
if (error)
g_return_val_if_fail (*error == NULL, FALSE);
return NM_VPN_EDITOR_GET_INTERFACE (editor)->update_connection (editor, connection, error);
}

69
libnm/nm-vpn-editor.c Normal file
View file

@ -0,0 +1,69 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2008 - 2010 Red Hat, Inc.
* Copyright 2008 Novell, Inc.
*/
#include "config.h"
#include "nm-vpn-editor.h"
static void nm_vpn_editor_default_init (NMVpnEditorInterface *iface);
G_DEFINE_INTERFACE (NMVpnEditor, nm_vpn_editor, G_TYPE_OBJECT)
static void
nm_vpn_editor_default_init (NMVpnEditorInterface *iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (iface);
/* Signals */
g_signal_new ("changed",
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMVpnEditorInterface, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
/**
* nm_vpn_editor_get_widget:
*
* Returns: (transfer none):
*/
GObject *
nm_vpn_editor_get_widget (NMVpnEditor *editor)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), NULL);
return NM_VPN_EDITOR_GET_INTERFACE (editor)->get_widget (editor);
}
gboolean
nm_vpn_editor_update_connection (NMVpnEditor *editor,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), FALSE);
if (error)
g_return_val_if_fail (*error == NULL, FALSE);
return NM_VPN_EDITOR_GET_INTERFACE (editor)->update_connection (editor, connection, error);
}

86
libnm/nm-vpn-editor.h Normal file
View file

@ -0,0 +1,86 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2008 Novell, Inc.
* Copyright 2008 - 2015 Red Hat, Inc.
*/
#ifndef __NM_VPN_EDITOR_H__
#define __NM_VPN_EDITOR_H__
#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include <glib.h>
#include <glib-object.h>
#include <nm-types.h>
#include "nm-vpn-editor-plugin.h"
G_BEGIN_DECLS
/**************************************************/
/* Editor interface */
/**************************************************/
#define NM_TYPE_VPN_EDITOR (nm_vpn_editor_get_type ())
#define NM_VPN_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_EDITOR, NMVpnEditor))
#define NM_IS_VPN_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_EDITOR))
#define NM_VPN_EDITOR_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_EDITOR, NMVpnEditorInterface))
/**
* NMVpnEditorInterface:
* @g_iface: the parent interface
* @get_widget: return the #GtkWidget for the VPN editor's UI
* @placeholder: not currently used
* @update_connection: called to save the user-entered options to the connection
* object. Should return %FALSE and set @error if the current options are
* invalid. @error should contain enough information for the plugin to
* determine which UI widget is invalid at a later point in time. For
* example, creating unique error codes for what error occurred and populating
* the message field of @error with the name of the invalid property.
* @changed: emitted when the value of a UI widget changes. May trigger a
* validity check via @update_connection to write values to the connection.
*
* Interface for editing a specific #NMConnection
*/
typedef struct {
GTypeInterface g_iface;
GObject * (*get_widget) (NMVpnEditor *editor);
void (*placeholder) (void);
gboolean (*update_connection) (NMVpnEditor *editor,
NMConnection *connection,
GError **error);
void (*changed) (NMVpnEditor *editor);
} NMVpnEditorInterface;
GType nm_vpn_editor_get_type (void);
GObject * nm_vpn_editor_get_widget (NMVpnEditor *editor);
gboolean nm_vpn_editor_update_connection (NMVpnEditor *editor,
NMConnection *connection,
GError **error);
G_END_DECLS
#endif /* __NM_VPN_EDITOR_H__ */

View file

@ -19,10 +19,6 @@
* Copyright 2007 - 2008 Red Hat, Inc.
*/
/* This interface is expected to be deprecated in NM 1.2, at which point there
* will be a new "NMVpnPlugin" class to replace it.
*/
#include "config.h"
#include <errno.h>
@ -70,7 +66,7 @@ typedef struct {
gboolean has_ip6, got_ip6;
/* Config stuff copied from config to ip4config */
char *banner, *tundev, *gateway, *mtu;
GVariant *banner, *tundev, *gateway, *mtu;
} NMVpnPluginOldPrivate;
#define NM_VPN_PLUGIN_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN_OLD, NMVpnPluginOldPrivate))
@ -117,6 +113,8 @@ nm_vpn_plugin_old_set_connection (NMVpnPluginOld *plugin,
* nm_vpn_plugin_old_get_connection:
*
* Returns: (transfer full):
*
* Deprecated: 1.2: replaced by NMVpnServicePlugin
*/
GDBusConnection *
nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin)
@ -300,14 +298,22 @@ nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin,
/* Record the items that need to also be inserted into the
* ip4config, for compatibility with older daemons.
*/
g_clear_pointer (&priv->banner, g_free);
(void) g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_BANNER, "&s", &priv->banner);
g_clear_pointer (&priv->tundev, g_free);
(void) g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_TUNDEV, "&s", &priv->tundev);
g_clear_pointer (&priv->gateway, g_free);
(void) g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, "&s", &priv->gateway);
g_clear_pointer (&priv->mtu, g_free);
(void) g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_MTU, "&s", &priv->mtu);
if (priv->banner)
g_variant_unref (priv->banner);
priv->banner = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_BANNER,
G_VARIANT_TYPE ("s"));
if (priv->tundev)
g_variant_unref (priv->tundev);
priv->tundev = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_TUNDEV,
G_VARIANT_TYPE ("s"));
if (priv->gateway)
g_variant_unref (priv->gateway);
priv->gateway = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY,
G_VARIANT_TYPE ("u"));
if (priv->mtu)
g_variant_unref (priv->mtu);
priv->mtu = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_MTU,
G_VARIANT_TYPE ("u"));
g_signal_emit (plugin, signals[CONFIG], 0, config);
}
@ -320,7 +326,8 @@ nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin,
GVariant *combined_config;
GVariantBuilder builder;
GVariantIter iter;
const char *key, *value;
const char *key;
GVariant *value;
g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
g_return_if_fail (ip4_config != NULL);
@ -340,19 +347,21 @@ nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin,
* being emitted. So just copy all of that data into the ip4
* config too.
*/
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_iter_init (&iter, ip4_config);
while (g_variant_iter_next (&iter, "{&s&s}", &key, &value))
g_variant_builder_add (&builder, "{ss}", key, value);
while (g_variant_iter_next (&iter, "{&sv}", &key, &value)) {
g_variant_builder_add (&builder, "{sv}", key, value);
g_variant_unref (value);
}
if (priv->banner)
g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner);
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner);
if (priv->tundev)
g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev);
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev);
if (priv->gateway)
g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway);
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway);
if (priv->mtu)
g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu);
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu);
combined_config = g_variant_builder_end (&builder);
g_variant_ref_sink (combined_config);
@ -595,6 +604,8 @@ impl_vpn_plugin_old_new_secrets (NMVpnPluginOld *plugin,
* request new secrets when the secrets originally provided by NetworkManager
* are insufficient, or the VPN process indicates that it needs additional
* information to complete the request.
*
* Deprecated: 1.2: replaced by NMVpnServicePlugin
*/
void
nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin,
@ -647,6 +658,8 @@ free_secret (gpointer data)
* an applet when the applet calls the authentication dialog of the VPN plugin.
*
* Returns: %TRUE if reading values was successful, %FALSE if not
*
* Deprecated: 1.2: replaced by NMVpnServicePlugin
**/
gboolean
nm_vpn_plugin_old_read_vpn_details (int fd,
@ -748,6 +761,8 @@ nm_vpn_plugin_old_read_vpn_details (int fd,
*
* Returns: %TRUE if the flag data item was found and successfully converted
* to flags, %FALSE if not
*
* Deprecated: 1.2: replaced by NMVpnServicePlugin
**/
gboolean
nm_vpn_plugin_old_get_secret_flags (GHashTable *data,
@ -1026,10 +1041,10 @@ finalize (GObject *object)
nm_vpn_plugin_old_set_connection (plugin, NULL);
g_free (priv->dbus_service_name);
g_clear_pointer (&priv->banner, g_free);
g_clear_pointer (&priv->tundev, g_free);
g_clear_pointer (&priv->gateway, g_free);
g_clear_pointer (&priv->mtu, g_free);
g_clear_pointer (&priv->banner, g_variant_unref);
g_clear_pointer (&priv->tundev, g_variant_unref);
g_clear_pointer (&priv->gateway, g_variant_unref);
g_clear_pointer (&priv->mtu, g_variant_unref);
G_OBJECT_CLASS (nm_vpn_plugin_old_parent_class)->finalize (object);
}
@ -1077,6 +1092,8 @@ nm_vpn_plugin_old_class_init (NMVpnPluginOldClass *plugin_class)
* NMVpnPluginOld:service-name:
*
* The D-Bus service name of this plugin.
*
* Deprecated: 1.2: replaced by NMVpnServicePlugin
*/
g_object_class_install_property
(object_class, PROP_DBUS_SERVICE_NAME,
@ -1090,6 +1107,8 @@ nm_vpn_plugin_old_class_init (NMVpnPluginOldClass *plugin_class)
* NMVpnPluginOld:state:
*
* The state of the plugin.
*
* Deprecated: 1.2: replaced by NMVpnServicePlugin
*/
g_object_class_install_property
(object_class, PROP_STATE,

View file

@ -16,7 +16,7 @@
* Boston, MA 02110-1301 USA.
*
* Copyright 2007 - 2008 Novell, Inc.
* Copyright 2007 - 2013 Red Hat, Inc.
* Copyright 2007 - 2015 Red Hat, Inc.
*/
#ifndef __NM_VPN_PLUGIN_OLD_H__
@ -39,94 +39,122 @@ G_BEGIN_DECLS
#define NM_VPN_PLUGIN_OLD_STATE "state"
typedef struct {
NM_DEPRECATED_IN_1_2
GObject parent;
} NMVpnPluginOld;
} NMVpnPluginOld NM_DEPRECATED_IN_1_2;
typedef struct {
NM_DEPRECATED_IN_1_2
GObjectClass parent;
/* Signals */
NM_DEPRECATED_IN_1_2
void (*state_changed) (NMVpnPluginOld *plugin,
NMVpnServiceState state);
NM_DEPRECATED_IN_1_2
void (*ip4_config) (NMVpnPluginOld *plugin,
GVariant *ip4_config);
NM_DEPRECATED_IN_1_2
void (*login_banner) (NMVpnPluginOld *plugin,
const char *banner);
NM_DEPRECATED_IN_1_2
void (*failure) (NMVpnPluginOld *plugin,
NMVpnPluginFailure reason);
NM_DEPRECATED_IN_1_2
void (*quit) (NMVpnPluginOld *plugin);
NM_DEPRECATED_IN_1_2
void (*config) (NMVpnPluginOld *plugin,
GVariant *config);
NM_DEPRECATED_IN_1_2
void (*ip6_config) (NMVpnPluginOld *plugin,
GVariant *config);
/* virtual methods */
NM_DEPRECATED_IN_1_2
gboolean (*connect) (NMVpnPluginOld *plugin,
NMConnection *connection,
GError **err);
NM_DEPRECATED_IN_1_2
gboolean (*need_secrets) (NMVpnPluginOld *plugin,
NMConnection *connection,
const char **setting_name,
GError **error);
NM_DEPRECATED_IN_1_2
gboolean (*disconnect) (NMVpnPluginOld *plugin,
GError **err);
NM_DEPRECATED_IN_1_2
gboolean (*new_secrets) (NMVpnPluginOld *plugin,
NMConnection *connection,
GError **error);
NM_DEPRECATED_IN_1_2
gboolean (*connect_interactive) (NMVpnPluginOld *plugin,
NMConnection *connection,
GVariant *details,
GError **error);
/*< private >*/
NM_DEPRECATED_IN_1_2
gpointer padding[8];
} NMVpnPluginOldClass;
} NMVpnPluginOldClass NM_DEPRECATED_IN_1_2;
NM_DEPRECATED_IN_1_2
GType nm_vpn_plugin_old_get_type (void);
NM_DEPRECATED_IN_1_2
GDBusConnection *nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin);
NM_DEPRECATED_IN_1_2
NMVpnServiceState nm_vpn_plugin_old_get_state (NMVpnPluginOld *plugin);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_set_state (NMVpnPluginOld *plugin,
NMVpnServiceState state);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin,
const char *message,
const char **hints);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_set_login_banner (NMVpnPluginOld *plugin,
const char *banner);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_failure (NMVpnPluginOld *plugin,
NMVpnPluginFailure reason);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin,
GVariant *config);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin,
GVariant *ip4_config);
NM_DEPRECATED_IN_1_2
void nm_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin,
GVariant *ip6_config);
NM_DEPRECATED_IN_1_2
gboolean nm_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin,
GError **err);
/* Utility functions */
NM_DEPRECATED_IN_1_2
gboolean nm_vpn_plugin_old_read_vpn_details (int fd,
GHashTable **out_data,
GHashTable **out_secrets);
NM_DEPRECATED_IN_1_2
gboolean nm_vpn_plugin_old_get_secret_flags (GHashTable *data,
const char *secret_name,
NMSettingSecretFlags *out_flags);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,164 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2007 - 2008 Novell, Inc.
* Copyright 2007 - 2015 Red Hat, Inc.
*/
#ifndef __NM_VPN_SERVICE_PLUGIN_H__
#define __NM_VPN_SERVICE_PLUGIN_H__
#include <gio/gio.h>
#include <nm-vpn-dbus-interface.h>
#include <nm-connection.h>
G_BEGIN_DECLS
#define NM_TYPE_VPN_SERVICE_PLUGIN (nm_vpn_service_plugin_get_type ())
#define NM_VPN_SERVICE_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_SERVICE_PLUGIN, NMVpnServicePlugin))
#define NM_VPN_SERVICE_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_SERVICE_PLUGIN, NMVpnServicePluginClass))
#define NM_IS_VPN_SERVICE_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_SERVICE_PLUGIN))
#define NM_IS_VPN_SERVICE_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_VPN_SERVICE_PLUGIN))
#define NM_VPN_SERVICE_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_SERVICE_PLUGIN, NMVpnServicePluginClass))
#define NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME "service-name"
#define NM_VPN_SERVICE_PLUGIN_STATE "state"
typedef struct {
NM_AVAILABLE_IN_1_2
GObject parent;
} NMVpnServicePlugin NM_AVAILABLE_IN_1_2;
typedef struct {
NM_AVAILABLE_IN_1_2
GObjectClass parent;
/* Signals */
NM_AVAILABLE_IN_1_2
void (*state_changed) (NMVpnServicePlugin *plugin,
NMVpnServiceState state);
NM_AVAILABLE_IN_1_2
void (*ip4_config) (NMVpnServicePlugin *plugin,
GVariant *ip4_config);
NM_AVAILABLE_IN_1_2
void (*login_banner) (NMVpnServicePlugin *plugin,
const char *banner);
NM_AVAILABLE_IN_1_2
void (*failure) (NMVpnServicePlugin *plugin,
NMVpnPluginFailure reason);
NM_AVAILABLE_IN_1_2
void (*quit) (NMVpnServicePlugin *plugin);
NM_AVAILABLE_IN_1_2
void (*config) (NMVpnServicePlugin *plugin,
GVariant *config);
NM_AVAILABLE_IN_1_2
void (*ip6_config) (NMVpnServicePlugin *plugin,
GVariant *config);
/* virtual methods */
NM_AVAILABLE_IN_1_2
gboolean (*connect) (NMVpnServicePlugin *plugin,
NMConnection *connection,
GError **err);
NM_AVAILABLE_IN_1_2
gboolean (*need_secrets) (NMVpnServicePlugin *plugin,
NMConnection *connection,
const char **setting_name,
GError **error);
NM_AVAILABLE_IN_1_2
gboolean (*disconnect) (NMVpnServicePlugin *plugin,
GError **err);
NM_AVAILABLE_IN_1_2
gboolean (*new_secrets) (NMVpnServicePlugin *plugin,
NMConnection *connection,
GError **error);
NM_AVAILABLE_IN_1_2
gboolean (*connect_interactive) (NMVpnServicePlugin *plugin,
NMConnection *connection,
GVariant *details,
GError **error);
/*< private >*/
NM_AVAILABLE_IN_1_2
gpointer padding[8];
} NMVpnServicePluginClass NM_AVAILABLE_IN_1_2;
NM_AVAILABLE_IN_1_2
GType nm_vpn_service_plugin_get_type (void);
NM_AVAILABLE_IN_1_2
GDBusConnection *nm_vpn_service_plugin_get_connection (NMVpnServicePlugin *plugin);
NM_AVAILABLE_IN_1_2
NMVpnServiceState nm_vpn_service_plugin_get_state (NMVpnServicePlugin *plugin);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_set_state (NMVpnServicePlugin *plugin,
NMVpnServiceState state);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_secrets_required (NMVpnServicePlugin *plugin,
const char *message,
const char **hints);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_set_login_banner (NMVpnServicePlugin *plugin,
const char *banner);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_failure (NMVpnServicePlugin *plugin,
NMVpnPluginFailure reason);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_set_config (NMVpnServicePlugin *plugin,
GVariant *config);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_set_ip4_config (NMVpnServicePlugin *plugin,
GVariant *ip4_config);
NM_AVAILABLE_IN_1_2
void nm_vpn_service_plugin_set_ip6_config (NMVpnServicePlugin *plugin,
GVariant *ip6_config);
NM_AVAILABLE_IN_1_2
gboolean nm_vpn_service_plugin_disconnect (NMVpnServicePlugin *plugin,
GError **err);
/* Utility functions */
NM_AVAILABLE_IN_1_2
gboolean nm_vpn_service_plugin_read_vpn_details (int fd,
GHashTable **out_data,
GHashTable **out_secrets);
NM_AVAILABLE_IN_1_2
gboolean nm_vpn_service_plugin_get_secret_flags (GHashTable *data,
const char *secret_name,
NMSettingSecretFlags *out_flags);
G_END_DECLS
#endif /* __NM_VPN_SERVICE_PLUGIN_H__ */

View file

@ -77,6 +77,8 @@ 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
libnm-util/crypto.c
@ -127,6 +129,7 @@ libnm/nm-object.c
libnm/nm-remote-connection.c
libnm/nm-remote-settings.c
libnm/nm-vpn-plugin-old.c
libnm/nm-vpn-service-plugin.c
policy/org.freedesktop.NetworkManager.policy.in.in
src/NetworkManagerUtils.c
src/main.c

View file

@ -29,44 +29,38 @@
#include "nm-vpn-connection.h"
#include "nm-setting-vpn.h"
#include "nm-vpn-dbus-interface.h"
#include "nm-core-internal.h"
#include "nm-enum-types.h"
#include "nm-logging.h"
#define VPN_NAME_FILES_DIR NMCONFDIR "/VPN"
#include "gsystem-local-alloc.h"
G_DEFINE_TYPE (NMVpnManager, nm_vpn_manager, G_TYPE_OBJECT)
#define NM_VPN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_MANAGER, NMVpnManagerPrivate))
typedef struct {
GHashTable *services;
GFileMonitor *monitor;
guint monitor_id;
GSList *services;
GFileMonitor *monitor_etc;
GFileMonitor *monitor_lib;
guint monitor_id_etc;
guint monitor_id_lib;
} NMVpnManagerPrivate;
static NMVpnService *
get_service_by_namefile (NMVpnManager *self, const char *namefile)
_plugin_info_get_service (NMVpnPluginInfo *plugin_info)
{
NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
gpointer data;
g_return_val_if_fail (namefile, NULL);
g_return_val_if_fail (g_path_is_absolute (namefile), NULL);
g_hash_table_iter_init (&iter, priv->services);
while (g_hash_table_iter_next (&iter, NULL, &data)) {
NMVpnService *candidate = NM_VPN_SERVICE (data);
const char *service_namefile;
service_namefile = nm_vpn_service_get_name_file (candidate);
if (!strcmp (namefile, service_namefile))
return candidate;
}
if (plugin_info)
return NM_VPN_SERVICE (g_object_get_data (G_OBJECT (plugin_info), "service-instance"));
return NULL;
}
static void
_plugin_info_set_service (NMVpnPluginInfo *plugin_info, NMVpnService *service)
{
g_object_set_data_full (G_OBJECT (plugin_info), "service-instance", service,
(GDestroyNotify) g_object_unref);
}
gboolean
nm_vpn_manager_activate_connection (NMVpnManager *manager,
NMVpnConnection *vpn,
@ -75,6 +69,7 @@ nm_vpn_manager_activate_connection (NMVpnManager *manager,
NMConnection *connection;
NMSettingVpn *s_vpn;
NMVpnService *service;
NMVpnPluginInfo *plugin_info;
const char *service_name;
NMDevice *device;
@ -98,8 +93,8 @@ nm_vpn_manager_activate_connection (NMVpnManager *manager,
g_assert (s_vpn);
service_name = nm_setting_vpn_get_service_type (s_vpn);
g_assert (service_name);
service = g_hash_table_lookup (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, service_name);
plugin_info = nm_vpn_plugin_info_list_find_by_service (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, service_name);
service = _plugin_info_get_service (plugin_info);
if (!service) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE,
"The VPN service '%s' was not installed.",
@ -119,33 +114,31 @@ nm_vpn_manager_deactivate_connection (NMVpnManager *self,
}
static void
try_add_service (NMVpnManager *self, const char *namefile)
try_add_service (NMVpnManager *self, NMVpnPluginInfo *plugin_info)
{
NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
NMVpnService *service = NULL;
GHashTableIter iter;
GError *error = NULL;
const char *service_name;
g_return_if_fail (g_path_is_absolute (namefile));
/* Make sure we don't add dupes */
g_hash_table_iter_init (&iter, priv->services);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) {
if (g_strcmp0 (namefile, nm_vpn_service_get_name_file (service)) == 0)
return;
}
/* Make sure we don't add dupes.
* We don't really allow reload of the same file. What we do allow is however to
* delete a file and re-add it. */
if (nm_vpn_plugin_info_list_find_by_filename (priv->services,
nm_vpn_plugin_info_get_filename (plugin_info)))
return;
if (!nm_vpn_plugin_info_list_add (&priv->services, plugin_info, NULL))
return;
/* New service */
service = nm_vpn_service_new (namefile, &error);
service = nm_vpn_service_new (plugin_info, &error);
if (service) {
service_name = nm_vpn_service_get_dbus_service (service);
g_hash_table_insert (priv->services, (char *) service_name, service);
nm_log_info (LOGD_VPN, "VPN: loaded %s", service_name);
_plugin_info_set_service (plugin_info, service);
nm_log_info (LOGD_VPN, "VPN: loaded %s - %s",
nm_vpn_plugin_info_get_name (plugin_info),
nm_vpn_service_get_dbus_service (service));
} else {
nm_log_warn (LOGD_VPN, "failed to load VPN service file %s: (%d) %s",
namefile,
error ? error->code : -1,
nm_log_warn (LOGD_VPN, "failed to load VPN service file %s: %s",
nm_vpn_plugin_info_get_filename (plugin_info),
error && error->message ? error->message : "(unknown)");
g_clear_error (&error);
}
@ -160,41 +153,65 @@ vpn_dir_changed (GFileMonitor *monitor,
{
NMVpnManager *self = NM_VPN_MANAGER (user_data);
NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
NMVpnPluginInfo *plugin_info;
NMVpnService *service;
char *path;
gs_free char *path = NULL;
GError *error = NULL;
path = g_file_get_path (file);
if (!g_str_has_suffix (path, ".name")) {
g_free (path);
if (!nm_vpn_plugin_info_validate_filename (path))
return;
}
switch (event_type) {
case G_FILE_MONITOR_EVENT_DELETED:
nm_log_dbg (LOGD_VPN, "service file %s deleted", path);
plugin_info = nm_vpn_plugin_info_list_find_by_filename (priv->services, path);
if (!plugin_info)
break;
service = get_service_by_namefile (self, path);
nm_log_dbg (LOGD_VPN, "vpn: service file %s deleted", path);
service = _plugin_info_get_service (plugin_info);
if (service) {
const char *service_name = nm_vpn_service_get_dbus_service (service);
/* Stop active VPN connections and destroy the service */
nm_vpn_service_stop_connections (service, FALSE,
NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
nm_log_info (LOGD_VPN, "VPN: unloaded %s", service_name);
g_hash_table_remove (priv->services, service_name);
nm_log_info (LOGD_VPN, "VPN: unloaded %s", nm_vpn_service_get_dbus_service (service));
_plugin_info_set_service (plugin_info, NULL);
}
nm_vpn_plugin_info_list_remove (&priv->services, plugin_info);
break;
case G_FILE_MONITOR_EVENT_CREATED:
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
nm_log_dbg (LOGD_VPN, "service file %s created or modified", path);
try_add_service (self, path);
plugin_info = nm_vpn_plugin_info_list_find_by_filename (priv->services, path);
if (plugin_info) {
/* we don't support reloading an existing plugin. You can only remove the file
* and re-add it. By reloading we want to support the use case of installing
* a VPN plugin after NM started. No need to burden ourself with a complete
* reload. */
break;
}
if (!_nm_vpn_plugin_info_check_file (path, TRUE, TRUE, 0,
NULL, NULL, &error)) {
nm_log_dbg (LOGD_VPN, "vpn: ignore changed service file %s (%s)", path, error->message);
g_clear_error (&error);
break;
}
plugin_info = nm_vpn_plugin_info_new_from_file (path, &error);
if (!plugin_info) {
nm_log_dbg (LOGD_VPN, "vpn: ignore changed service file %s due to invalid content (%s)", path, error->message);
g_clear_error (&error);
break;
}
nm_log_dbg (LOGD_VPN, "vpn: service file %s created or modified", path);
try_add_service (self, plugin_info);
g_object_unref (plugin_info);
break;
default:
nm_log_dbg (LOGD_VPN, "service file %s change event %d", path, event_type);
nm_log_dbg (LOGD_VPN, "vpn: service file %s change event %d", path, event_type);
break;
}
g_free (path);
}
/******************************************************************************/
@ -206,50 +223,40 @@ nm_vpn_manager_init (NMVpnManager *self)
{
NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
GFile *file;
GDir *dir;
const char *fn;
char *path;
priv->services = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, g_object_unref);
GSList *infos, *info;
const char *conf_dir_etc = _nm_vpn_plugin_info_get_default_dir_etc ();
const char *conf_dir_lib = _nm_vpn_plugin_info_get_default_dir_lib ();
/* Watch the VPN directory for changes */
file = g_file_new_for_path (VPN_NAME_FILES_DIR "/");
priv->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
file = g_file_new_for_path (conf_dir_lib);
priv->monitor_lib = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
if (priv->monitor) {
priv->monitor_id = g_signal_connect (priv->monitor, "changed",
G_CALLBACK (vpn_dir_changed), self);
if (priv->monitor_lib) {
priv->monitor_id_lib = g_signal_connect (priv->monitor_lib, "changed",
G_CALLBACK (vpn_dir_changed), self);
}
/* Load VPN service files */
dir = g_dir_open (VPN_NAME_FILES_DIR, 0, NULL);
if (dir) {
while ((fn = g_dir_read_name (dir))) {
/* only parse filenames that end with .name */
if (g_str_has_suffix (fn, ".name")) {
path = g_build_filename (VPN_NAME_FILES_DIR, fn, NULL);
try_add_service (self, path);
g_free (path);
}
}
g_dir_close (dir);
file = g_file_new_for_path (conf_dir_etc);
priv->monitor_etc = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
if (priv->monitor_etc) {
priv->monitor_id_etc = g_signal_connect (priv->monitor_etc, "changed",
G_CALLBACK (vpn_dir_changed), self);
}
}
static void
stop_all_services (NMVpnManager *self)
{
NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
NMVpnService *service;
/* first read conf_dir_lib. The name files are not really user configuration, but
* plugin configuration. Hence we expect ~newer~ plugins to install their files
* in /usr/lib/NetworkManager. We want to prefer those files.
* In case of no-conflict, the order doesn't matter. */
infos = _nm_vpn_plugin_info_list_load_dir (conf_dir_lib, TRUE, 0, NULL, NULL);
for (info = infos; info; info = info->next)
try_add_service (self, info->data);
g_slist_free_full (infos, g_object_unref);
g_hash_table_iter_init (&iter, priv->services);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) {
nm_vpn_service_stop_connections (service,
TRUE,
NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
}
infos = _nm_vpn_plugin_info_list_load_dir (conf_dir_etc, TRUE, 0, NULL, NULL);
for (info = infos; info; info = info->next)
try_add_service (self, info->data);
g_slist_free_full (infos, g_object_unref);
}
static void
@ -257,17 +264,29 @@ dispose (GObject *object)
{
NMVpnManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (object);
if (priv->monitor) {
if (priv->monitor_id)
g_signal_handler_disconnect (priv->monitor, priv->monitor_id);
g_file_monitor_cancel (priv->monitor);
g_clear_object (&priv->monitor);
if (priv->monitor_etc) {
if (priv->monitor_id_etc)
g_signal_handler_disconnect (priv->monitor_etc, priv->monitor_id_etc);
g_file_monitor_cancel (priv->monitor_etc);
g_clear_object (&priv->monitor_etc);
}
if (priv->services) {
stop_all_services (NM_VPN_MANAGER (object));
g_hash_table_destroy (priv->services);
priv->services = NULL;
if (priv->monitor_lib) {
if (priv->monitor_id_lib)
g_signal_handler_disconnect (priv->monitor_lib, priv->monitor_id_lib);
g_file_monitor_cancel (priv->monitor_lib);
g_clear_object (&priv->monitor_lib);
}
while (priv->services) {
NMVpnPluginInfo *plugin_info = priv->services->data;
NMVpnService *service = _plugin_info_get_service (plugin_info);
if (service) {
nm_vpn_service_stop_connections (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
_plugin_info_set_service (plugin_info, NULL);
}
nm_vpn_plugin_info_list_remove (&priv->services, plugin_info);
}
G_OBJECT_CLASS (nm_vpn_manager_parent_class)->dispose (object);

View file

@ -35,10 +35,7 @@
G_DEFINE_TYPE (NMVpnService, nm_vpn_service, G_TYPE_OBJECT)
typedef struct {
char *name;
char *dbus_service;
char *program;
char *namefile;
NMVpnPluginInfo *plugin_info;
NMVpnConnection *active;
GSList *pending;
@ -50,67 +47,50 @@ typedef struct {
#define NM_VPN_SERVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_SERVICE, NMVpnServicePrivate))
#define VPN_CONNECTION_GROUP "VPN Connection"
static gboolean start_pending_vpn (NMVpnService *self, GError **error);
static void _name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data);
NMVpnService *
nm_vpn_service_new (const char *namefile, GError **error)
nm_vpn_service_new (NMVpnPluginInfo *plugin_info, GError **error)
{
NMVpnService *self;
NMVpnServicePrivate *priv;
GKeyFile *kf;
g_return_val_if_fail (namefile != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (namefile), NULL);
g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (plugin_info), NULL);
g_return_val_if_fail (nm_vpn_plugin_info_get_filename (plugin_info), NULL);
kf = g_key_file_new ();
if (!g_key_file_load_from_file (kf, namefile, G_KEY_FILE_NONE, error)) {
g_key_file_free (kf);
if (!nm_vpn_plugin_info_get_program (plugin_info)) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
"missing \"program\" entry");
return NULL;
}
self = (NMVpnService *) g_object_new (NM_TYPE_VPN_SERVICE, NULL);
priv = NM_VPN_SERVICE_GET_PRIVATE (self);
priv->namefile = g_strdup (namefile);
priv->dbus_service = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "service", error);
if (!priv->dbus_service)
goto error;
priv->program = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "program", error);
if (!priv->program)
goto error;
priv->name = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "name", error);
if (!priv->name)
goto error;
priv->plugin_info = g_object_ref (plugin_info);
priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
priv->dbus_service,
nm_vpn_plugin_info_get_service (plugin_info),
NM_VPN_DBUS_PLUGIN_PATH,
NM_VPN_DBUS_PLUGIN_INTERFACE,
NULL, error);
if (!priv->proxy)
goto error;
if (!priv->proxy) {
g_object_unref (self);
return NULL;
}
g_signal_connect (priv->proxy, "notify::g-name-owner",
G_CALLBACK (_name_owner_changed), self);
_name_owner_changed (G_OBJECT (priv->proxy), NULL, self);
g_key_file_free (kf);
return self;
error:
g_object_unref (self);
g_key_file_free (kf);
return NULL;
}
const char *
@ -118,15 +98,7 @@ nm_vpn_service_get_dbus_service (NMVpnService *service)
{
g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL);
return NM_VPN_SERVICE_GET_PRIVATE (service)->dbus_service;
}
const char *
nm_vpn_service_get_name_file (NMVpnService *service)
{
g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL);
return NM_VPN_SERVICE_GET_PRIVATE (service)->namefile;
return nm_vpn_plugin_info_get_service (NM_VPN_SERVICE_GET_PRIVATE (service)->plugin_info);
}
static void
@ -187,7 +159,7 @@ _daemon_exec_timeout (gpointer data)
NMVpnService *self = NM_VPN_SERVICE (data);
NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self);
nm_log_warn (LOGD_VPN, "VPN service '%s' start timed out", priv->name);
nm_log_warn (LOGD_VPN, "VPN service '%s' start timed out", nm_vpn_plugin_info_get_name (priv->plugin_info));
priv->start_timeout = 0;
nm_vpn_service_stop_connections (self, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT);
return G_SOURCE_REMOVE;
@ -204,17 +176,21 @@ nm_vpn_service_daemon_exec (NMVpnService *service, GError **error)
g_return_val_if_fail (NM_IS_VPN_SERVICE (service), FALSE);
vpn_argv[0] = priv->program;
vpn_argv[0] = (char *) nm_vpn_plugin_info_get_program (priv->plugin_info);
vpn_argv[1] = NULL;
g_assert (vpn_argv[0]);
success = g_spawn_async (NULL, vpn_argv, NULL, 0, nm_utils_setpgid, NULL, &pid, &spawn_error);
if (success) {
nm_log_info (LOGD_VPN, "VPN service '%s' started (%s), PID %ld",
priv->name, priv->dbus_service, (long int) pid);
nm_vpn_plugin_info_get_name (priv->plugin_info),
nm_vpn_service_get_dbus_service (service),
(long int) pid);
priv->start_timeout = g_timeout_add_seconds (5, _daemon_exec_timeout, service);
} else {
nm_log_warn (LOGD_VPN, "VPN service '%s': could not launch the VPN service. error: (%d) %s.",
priv->name,
nm_vpn_plugin_info_get_name (priv->plugin_info),
spawn_error ? spawn_error->code : -1,
spawn_error && spawn_error->message ? spawn_error->message : "(unknown)");
@ -244,7 +220,7 @@ start_active_vpn (NMVpnService *self, GError **error)
return TRUE;
} else if (priv->start_timeout == 0) {
/* VPN service not running, start it */
nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", priv->name);
nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", nm_vpn_plugin_info_get_name (priv->plugin_info));
return nm_vpn_service_daemon_exec (self, error);
}
@ -324,14 +300,14 @@ _name_owner_changed (GObject *object,
if (owner && !priv->service_running) {
/* service appeared */
priv->service_running = TRUE;
nm_log_info (LOGD_VPN, "VPN service '%s' appeared; activating connections", priv->name);
nm_log_info (LOGD_VPN, "VPN service '%s' appeared; activating connections", nm_vpn_plugin_info_get_name (priv->plugin_info));
/* Expect success because the VPN service has already appeared */
success = start_active_vpn (service, NULL);
g_warn_if_fail (success);
} else if (!owner && priv->service_running) {
/* service went away */
priv->service_running = FALSE;
nm_log_info (LOGD_VPN, "VPN service '%s' disappeared", priv->name);
nm_log_info (LOGD_VPN, "VPN service '%s' disappeared", nm_vpn_plugin_info_get_name (priv->plugin_info));
nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
}
@ -351,10 +327,9 @@ dispose (GObject *object)
NMVpnService *self = NM_VPN_SERVICE (object);
NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self);
if (priv->start_timeout) {
g_source_remove (priv->start_timeout);
priv->start_timeout = 0;
}
nm_clear_g_source (&priv->start_timeout);
g_clear_object (&priv->plugin_info);
/* VPNService owner is required to stop connections before releasing */
g_assert (priv->active == NULL);
@ -370,19 +345,6 @@ dispose (GObject *object)
G_OBJECT_CLASS (nm_vpn_service_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
NMVpnServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (object);
g_free (priv->name);
g_free (priv->dbus_service);
g_free (priv->program);
g_free (priv->namefile);
G_OBJECT_CLASS (nm_vpn_service_parent_class)->finalize (object);
}
static void
nm_vpn_service_class_init (NMVpnServiceClass *service_class)
{
@ -392,5 +354,4 @@ nm_vpn_service_class_init (NMVpnServiceClass *service_class)
/* virtual methods */
object_class->dispose = dispose;
object_class->finalize = finalize;
}

View file

@ -25,6 +25,7 @@
#include "nm-glib.h"
#include "nm-device.h"
#include "nm-vpn-connection.h"
#include "nm-vpn-plugin-info.h"
#define NM_TYPE_VPN_SERVICE (nm_vpn_service_get_type ())
#define NM_VPN_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_SERVICE, NMVpnService))
@ -43,14 +44,11 @@ typedef struct {
GType nm_vpn_service_get_type (void);
NMVpnService * nm_vpn_service_new (const char *namefile, GError **error);
NMVpnService * nm_vpn_service_new (NMVpnPluginInfo *plugin_info, GError **error);
/* Returns the VPN service's D-Bus service name */
const char *nm_vpn_service_get_dbus_service (NMVpnService *service);
/* Returns the path of the VPN service's .name file */
const char *nm_vpn_service_get_name_file (NMVpnService *service);
gboolean nm_vpn_service_activate (NMVpnService *service,
NMVpnConnection *vpn,
GError **error);