mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-20 07:00:39 +01:00
libnm/vpn: add nm_vpn_editor_plugin_load_vt()
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.
This commit is contained in:
parent
1c42375efb
commit
cf34211c90
7 changed files with 260 additions and 1 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@ vpn-daemons/openvpn
|
|||
vpn-daemons/pptp
|
||||
vpn-daemons/vpnc
|
||||
contrib/fedora/rpm/
|
||||
shared/nm-vpn-editor-plugin-call.h
|
||||
# https://bugs.launchpad.net/intltool/+bug/1117944
|
||||
sub/policy/org.freedesktop.NetworkManager.policy.in
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
189
shared/nm-vpn-editor-plugin-call.h
Normal file
189
shared/nm-vpn-editor-plugin-call.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/* -*- 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.
|
||||
*
|
||||
* This uses the NMVpnEditorPluginVT and allows a user (nm-applet)
|
||||
* to directly communicate with a VPN plugin using API that is newer
|
||||
* then the current libnm version. That is, it allows to call to a VPN
|
||||
* plugin bypassing libnm. */
|
||||
|
||||
#include <NetworkManager.h>
|
||||
|
||||
/* we make use of other internal 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__ */
|
||||
Loading…
Add table
Reference in a new issue