summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-06-13 11:47:58 +0200
committerThomas Haller <thaller@redhat.com>2016-06-15 10:32:32 +0200
commit7b3c93829d8682c7443165c100c114744696b976 (patch)
tree896083d09a02b7a8a6713adae7b8803e771f23a6
parent1c42375efb56bccb2ed55153cfd82826f910cac1 (diff)
downloadNetworkManager-th/vpn-service-info-bgo767197.tar.gz
libnm/vpn: add nm_vpn_editor_plugin_load_vt()th/vpn-service-info-bgo767197
Let VPN plugins return a virtual function table to extend the API while bypassing libnm. This allows to add and use new functionality to VPN plugins without updating libnm. The actual definitions are in a header-only file "nm-vpn-editor-plugin-call.h", which can be copied to the caller/plugin.
-rw-r--r--libnm-core/nm-vpn-editor-plugin.c47
-rw-r--r--libnm-core/nm-vpn-editor-plugin.h12
-rw-r--r--libnm/libnm.ver1
-rw-r--r--libnm/nm-vpn-service-plugin.c8
-rw-r--r--po/POTFILES.skip1
-rw-r--r--shared/Makefile.am3
-rw-r--r--shared/nm-vpn-editor-plugin-call.h184
7 files changed, 255 insertions, 1 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c
index 1a4944b066..bc72ca3911 100644
--- a/libnm-core/nm-vpn-editor-plugin.c
+++ b/libnm-core/nm-vpn-editor-plugin.c
@@ -180,6 +180,53 @@ nm_vpn_editor_plugin_set_plugin_info (NMVpnEditorPlugin *plugin, NMVpnPluginInfo
/*********************************************************************/
+/**
+ * nm_vpn_editor_plugin_get_vt:
+ * @plugin: the #NMVpnEditorPlugin
+ * @vt: (out): buffer to be filled with the VT table of the plugin
+ * @vt_size: the size of the buffer. Can be 0 to only query the
+ * size of plugin's VT.
+ *
+ * Returns an opaque VT function table for the plugin to extend
+ * functionality. The actual meaning of NMVpnEditorPluginVT is not
+ * defined in public API of libnm, instead it must be agreed by
+ * both the plugin and the caller. See the header-only file
+ * 'nm-vpn-editor-plugin-call.h' which defines the meaning.
+ *
+ * Returns: the actual size of the @plugin's virtual function table.
+ *
+ * Since: 1.4
+ **/
+gsize
+nm_vpn_editor_plugin_get_vt (NMVpnEditorPlugin *plugin,
+ NMVpnEditorPluginVT *vt,
+ gsize vt_size)
+{
+ const NMVpnEditorPluginVT *p_vt = NULL;
+ gsize p_vt_size = 0;
+ NMVpnEditorPluginInterface *interface;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
+
+ if (vt_size) {
+ g_return_val_if_fail (vt, 0);
+ memset (vt, 0, vt_size);
+ }
+
+ interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin);
+ if (interface->get_vt) {
+ p_vt = interface->get_vt (plugin, &p_vt_size);
+ if (!p_vt)
+ p_vt_size = 0;
+ g_return_val_if_fail (p_vt_size, 0);
+ memcpy (vt, p_vt, MIN (vt_size, p_vt_size));
+ }
+
+ return p_vt_size;
+}
+
+/*********************************************************************/
+
static NMVpnEditorPlugin *
_nm_vpn_editor_plugin_load (const char *plugin_name,
gboolean do_file_checks,
diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h
index dc18f04b74..fb51f7e621 100644
--- a/libnm-core/nm-vpn-editor-plugin.h
+++ b/libnm-core/nm-vpn-editor-plugin.h
@@ -82,6 +82,8 @@ typedef enum /*< flags >*/ {
/* D-Bus service name of the plugin's VPN service */
#define NM_VPN_EDITOR_PLUGIN_SERVICE "service"
+typedef struct _NMVpnEditorPluginVT NMVpnEditorPluginVT;
+
/**
* NMVpnEditorPluginInterface:
* @g_iface: the parent interface
@@ -99,6 +101,8 @@ typedef enum /*< flags >*/ {
* @get_suggested_filename: For a given connection, return a suggested file
* name. Returned value will be %NULL or a suggested file name to be freed by
* the caller.
+ * @get_vt: return a virtual function table to implement further functions in
+ * the plugin, without requiring to update libnm. Used by nm_vpn_editor_plugin_get_vt().
*
* Interface for VPN editor plugins.
*/
@@ -124,6 +128,9 @@ typedef struct {
void (*notify_plugin_info_set) (NMVpnEditorPlugin *plugin,
struct _NMVpnPluginInfo *plugin_info);
+
+ const NMVpnEditorPluginVT *(*get_vt) (NMVpnEditorPlugin *plugin,
+ gsize *out_vt_size);
} NMVpnEditorPluginInterface;
GType nm_vpn_editor_plugin_get_type (void);
@@ -134,6 +141,11 @@ NMVpnEditor *nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
NMVpnEditorPluginCapability nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin);
+NM_AVAILABLE_IN_1_4
+gsize nm_vpn_editor_plugin_get_vt (NMVpnEditorPlugin *plugin,
+ NMVpnEditorPluginVT *vt,
+ gsize vt_size);
+
NMConnection *nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin,
const char *path,
GError **error);
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 2dc2103517..41f650f008 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1069,6 +1069,7 @@ global:
nm_setting_ip6_config_get_token;
nm_setting_ip_config_get_dns_priority;
nm_vpn_editor_plugin_get_plugin_info;
+ nm_vpn_editor_plugin_get_vt;
nm_vpn_editor_plugin_load;
nm_vpn_editor_plugin_set_plugin_info;
nm_vpn_plugin_info_get_aliases;
diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c
index bf4369e4ad..df99eb28d9 100644
--- a/libnm/nm-vpn-service-plugin.c
+++ b/libnm/nm-vpn-service-plugin.c
@@ -1306,3 +1306,11 @@ nm_vpn_service_plugin_initable_iface_init (GInitableIface *iface)
{
iface->init = init_sync;
}
+
+/*****************************************************************************/
+
+/* this header is intended to be copied to users of nm_vpn_editor_plugin_call(),
+ * to simplify invocation of generic functions. Include it here, to complile
+ * the code. */
+#include "nm-vpn-editor-plugin-call.h"
+
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 70e222c6a9..2e36b03a17 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -7,4 +7,5 @@ vpn-daemons/pptp
vpn-daemons/vpnc
contrib/fedora/rpm/
# https://bugs.launchpad.net/intltool/+bug/1117944
+shared/nm-vpn-editor-plugin-call.h
sub/policy/org.freedesktop.NetworkManager.policy.in
diff --git a/shared/Makefile.am b/shared/Makefile.am
index c6ede00b6a..01818d0cd1 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -10,6 +10,7 @@ EXTRA_DIST = \
nm-test-libnm-utils.h \
nm-test-utils.h \
nm-test-utils-impl.c \
- nm-version-macros.h.in
+ nm-version-macros.h.in \
+ nm-vpn-editor-plugin-call.h
CLEANFILES=nm-version.h
diff --git a/shared/nm-vpn-editor-plugin-call.h b/shared/nm-vpn-editor-plugin-call.h
new file mode 100644
index 0000000000..584f3787d5
--- /dev/null
+++ b/shared/nm-vpn-editor-plugin-call.h
@@ -0,0 +1,184 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_VPN_EDITOR_PLUGIN_CALL_H__
+#define __NM_VPN_EDITOR_PLUGIN_CALL_H__
+
+/* This header is an internal, header-only file that can be copied to
+ * other projects to call well-known service functions on VPN plugins. */
+
+#include <NetworkManager.h>
+
+/* we make use of otherinternal header files, you need those too. */
+#include "gsystem-local-alloc.h"
+#include "nm-macros-internal.h"
+
+/*****************************************************************************/
+
+/**
+ * NMVpnEditorPluginServiceFlags:
+ * @NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_NONE: no flags
+ * @NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD: whether the plugin can
+ * add a new connection for the given service-type.
+ **/
+typedef enum { /*< skip >*/
+ NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_NONE = 0x00,
+ NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD = 0x01,
+} NMVpnEditorPluginServiceFlags;
+
+struct _NMVpnEditorPluginVT {
+ gboolean (*fcn_get_service_info) (NMVpnEditorPlugin *plugin,
+ const char *service_type,
+ char **out_short_name,
+ char **out_pretty_name,
+ char **out_description,
+ NMVpnEditorPluginServiceFlags *out_flags);
+ char **(*fcn_get_service_add_details) (NMVpnEditorPlugin *plugin,
+ const char *service_name);
+ gboolean (*fcn_get_service_add_detail) (NMVpnEditorPlugin *plugin,
+ const char *service_type,
+ const char *add_detail,
+ char **out_pretty_name,
+ char **out_description,
+ char **out_add_detail_key,
+ char **out_add_detail_val,
+ guint *out_flags);
+};
+
+/*****************************************************************************
+ * Call
+ *
+ * The following wrap the calling of generic functions for a VPN plugin.
+ * They are used by callers (for example nm-connection-editor).
+ *****************************************************************************/
+
+static inline gboolean
+nm_vpn_editor_plugin_get_service_info (NMVpnEditorPlugin *plugin,
+ const char *service_type,
+ char **out_short_name,
+ char **out_pretty_name,
+ char **out_description,
+ NMVpnEditorPluginServiceFlags *out_flags)
+{
+ NMVpnEditorPluginVT vt;
+ gs_free char *short_name_local = NULL;
+ gs_free char *pretty_name_local = NULL;
+ gs_free char *description_local = NULL;
+ guint flags_local = 0;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+ g_return_val_if_fail (service_type, FALSE);
+
+ nm_vpn_editor_plugin_get_vt (plugin, &vt, sizeof (vt));
+ if ( !vt.fcn_get_service_info
+ || !vt.fcn_get_service_info (plugin,
+ service_type,
+ out_short_name ? &short_name_local : NULL,
+ out_pretty_name ? &pretty_name_local : NULL,
+ out_description ? &description_local : NULL,
+ out_flags ? &flags_local : NULL))
+ return FALSE;
+ NM_SET_OUT (out_short_name, g_steal_pointer (&short_name_local));
+ NM_SET_OUT (out_pretty_name, g_steal_pointer (&pretty_name_local));
+ NM_SET_OUT (out_description, g_steal_pointer (&description_local));
+ NM_SET_OUT (out_flags, flags_local);
+ return TRUE;
+}
+
+static inline char **
+nm_vpn_editor_plugin_get_service_add_details (NMVpnEditorPlugin *plugin,
+ const char *service_name)
+{
+ NMVpnEditorPluginVT vt;
+ char **details = NULL;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
+ g_return_val_if_fail (service_name, NULL);
+
+ nm_vpn_editor_plugin_get_vt (plugin, &vt, sizeof (vt));
+ if (vt.fcn_get_service_add_details)
+ details = vt.fcn_get_service_add_details (plugin, service_name);
+ if (!details)
+ return g_new0 (char *, 1);
+ return details;
+}
+
+static inline gboolean
+nm_vpn_editor_plugin_get_service_add_detail (NMVpnEditorPlugin *plugin,
+ const char *service_type,
+ const char *add_detail,
+ char **out_pretty_name,
+ char **out_description,
+ char **out_add_detail_key,
+ char **out_add_detail_val,
+ guint *out_flags)
+{
+ NMVpnEditorPluginVT vt;
+ gs_free char *pretty_name_local = NULL;
+ gs_free char *description_local = NULL;
+ gs_free char *add_detail_key_local = NULL;
+ gs_free char *add_detail_val_local = NULL;
+ guint flags_local = 0;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+ g_return_val_if_fail (service_type, FALSE);
+ g_return_val_if_fail (add_detail, FALSE);
+
+ nm_vpn_editor_plugin_get_vt (plugin, &vt, sizeof (vt));
+ if ( !vt.fcn_get_service_add_detail
+ || !vt.fcn_get_service_add_detail (plugin,
+ service_type,
+ add_detail,
+ out_pretty_name ? &pretty_name_local : NULL,
+ out_description ? &description_local : NULL,
+ out_add_detail_key ? &add_detail_key_local : NULL,
+ out_add_detail_val ? &add_detail_val_local : NULL,
+ out_flags ? &flags_local : NULL))
+ return FALSE;
+ NM_SET_OUT (out_pretty_name, g_steal_pointer (&pretty_name_local));
+ NM_SET_OUT (out_description, g_steal_pointer (&description_local));
+ NM_SET_OUT (out_add_detail_key, g_steal_pointer (&add_detail_key_local));
+ NM_SET_OUT (out_add_detail_val, g_steal_pointer (&add_detail_val_local));
+ NM_SET_OUT (out_flags, flags_local);
+ return TRUE;
+}
+
+/*****************************************************************************
+ * Implementation
+ *
+ * The following glue code can be used to implement calls in a VPN plugin.
+ *****************************************************************************/
+
+#define NM_VPN_EDITOR_PLUGIN_VT_DEFINE(vt_name, get_vt, ...) \
+static const NMVpnEditorPluginVT vt_name = { \
+ __VA_ARGS__ \
+ }; \
+static const NMVpnEditorPluginVT * \
+get_vt (NMVpnEditorPlugin *plugin, \
+ gsize *out_vt_size) \
+{ \
+ nm_assert (NM_IS_VPN_EDITOR_PLUGIN (plugin)); \
+ nm_assert (out_vt_size); \
+ \
+ *out_vt_size = sizeof (vt_name); \
+ return &vt_name; \
+}
+
+#endif /* __NM_VPN_EDITOR_PLUGIN_CALL_H__ */