diff options
Diffstat (limited to 'libnm-glib/nm-vpn-plugin.c')
| -rw-r--r-- | libnm-glib/nm-vpn-plugin.c | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c new file mode 100644 index 00000000..fe7a2b63 --- /dev/null +++ b/libnm-glib/nm-vpn-plugin.c @@ -0,0 +1,807 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2008 Red Hat, Inc. + */ + +#include <signal.h> +#include "nm-glib-compat.h" +#include "nm-vpn-plugin.h" +#include "nm-utils.h" +#include "nm-connection.h" +#include "nm-dbus-glib-types.h" + +static gboolean impl_vpn_plugin_connect (NMVPNPlugin *plugin, + GHashTable *connection, + GError **err); + +static gboolean impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin, + GHashTable *connection, + char **service_name, + GError **err); + +static gboolean impl_vpn_plugin_disconnect (NMVPNPlugin *plugin, + GError **err); + +static gboolean impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin, + GHashTable *config, + GError **err); + +static gboolean impl_vpn_plugin_set_failure (NMVPNPlugin *plugin, + char *reason, + GError **err); + +#include "nm-vpn-plugin-glue.h" + +#define NM_VPN_PLUGIN_CONNECT_TIMER 60 +#define NM_VPN_PLUGIN_QUIT_TIMER 20 + +G_DEFINE_ABSTRACT_TYPE (NMVPNPlugin, nm_vpn_plugin, G_TYPE_OBJECT) + +typedef struct { + NMVPNServiceState state; + + /* DBUS-y stuff */ + DBusGConnection *connection; + char *dbus_service_name; + + /* GObject-y stuff */ + gboolean disposed; + + /* Temporary stuff */ + guint connect_timer; + guint quit_timer; + guint fail_stop_id; +} NMVPNPluginPrivate; + +#define NM_VPN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN, NMVPNPluginPrivate)) + +enum { + STATE_CHANGED, + IP4_CONFIG, + LOGIN_BANNER, + FAILURE, + QUIT, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + PROP_DBUS_SERVICE_NAME, + PROP_STATE, + + LAST_PROP +}; + +static GSList *active_plugins = NULL; + + +GQuark +nm_vpn_plugin_error_quark (void) +{ + static GQuark quark = 0; + + if (!quark) + quark = g_quark_from_static_string ("nm_vpn_plugin_error"); + + return quark; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_vpn_plugin_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_GENERAL, "General"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, "StartingInProgress"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, "AlreadyStarted"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, "StoppingInProgress"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, "AlreadyStopped"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_WRONG_STATE, "WrongState"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "BadArguments"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "LaunchFailed"), + ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, "ConnectionInvalid"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("NMVPNPluginError", values); + } + + return etype; +} + + +static void +nm_vpn_plugin_set_connection (NMVPNPlugin *plugin, + DBusGConnection *connection) +{ + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + + if (priv->connection) + dbus_g_connection_unref (priv->connection); + + priv->connection = connection; +} + +DBusGConnection * +nm_vpn_plugin_get_connection (NMVPNPlugin *plugin) +{ + DBusGConnection *connection; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NULL); + + connection = NM_VPN_PLUGIN_GET_PRIVATE (plugin)->connection; + + if (connection) + dbus_g_connection_ref (connection); + + return connection; +} + +NMVPNServiceState +nm_vpn_plugin_get_state (NMVPNPlugin *plugin) +{ + g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_UNKNOWN); + + return NM_VPN_PLUGIN_GET_PRIVATE (plugin)->state; +} + +void +nm_vpn_plugin_set_state (NMVPNPlugin *plugin, + NMVPNServiceState state) +{ + NMVPNPluginPrivate *priv; + + g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); + + priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + if (priv->state != state) { + priv->state = state; + g_signal_emit (plugin, signals[STATE_CHANGED], 0, state); + } +} + +void +nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin, + const char *banner) +{ + g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); + g_return_if_fail (banner != NULL); + + g_signal_emit (plugin, signals[LOGIN_BANNER], 0, banner); +} + +void +nm_vpn_plugin_failure (NMVPNPlugin *plugin, + NMVPNPluginFailure reason) +{ + g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); + + g_signal_emit (plugin, signals[FAILURE], 0, reason); +} + +gboolean +nm_vpn_plugin_disconnect (NMVPNPlugin *plugin, GError **err) +{ + gboolean ret = FALSE; + NMVPNServiceState state; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); + + state = nm_vpn_plugin_get_state (plugin); + switch (state) { + case NM_VPN_SERVICE_STATE_STOPPING: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, + "%s", + "Could not process the request because the VPN connection is already being stopped."); + break; + case NM_VPN_SERVICE_STATE_STOPPED: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, + "%s", + "Could not process the request because no VPN connection was active."); + break; + case NM_VPN_SERVICE_STATE_STARTING: + case NM_VPN_SERVICE_STATE_STARTED: + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING); + ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->disconnect (plugin, err); + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); + break; + case NM_VPN_SERVICE_STATE_INIT: + ret = TRUE; + break; + + default: + g_warning ("Unhandled VPN service state %d", state); + g_assert_not_reached (); + break; + } + + return ret; +} + +static void +nm_vpn_plugin_emit_quit (NMVPNPlugin *plugin) +{ + g_signal_emit (plugin, signals[QUIT], 0); +} + +static gboolean +connect_timer_expired (gpointer data) +{ + NMVPNPlugin *plugin = NM_VPN_PLUGIN (data); + GError *err = NULL; + + nm_info ("Connect timer expired, disconnecting."); + nm_vpn_plugin_disconnect (plugin, &err); + if (err) { + nm_warning ("Disconnect failed: %s", err->message); + g_error_free (err); + } + + return FALSE; +} + +static gboolean +quit_timer_expired (gpointer data) +{ + NMVPNPlugin *plugin = NM_VPN_PLUGIN (data); + + nm_vpn_plugin_emit_quit (plugin); + + return FALSE; +} + +static gboolean +fail_stop (gpointer data) +{ + NMVPNPlugin *plugin = NM_VPN_PLUGIN (data); + + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); + return FALSE; +} + +static gboolean +nm_vpn_plugin_connect (NMVPNPlugin *plugin, + NMConnection *connection, + GError **err) +{ + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + gboolean ret = FALSE; + NMVPNServiceState state; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); + + state = nm_vpn_plugin_get_state (plugin); + switch (state) { + case NM_VPN_SERVICE_STATE_STARTING: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, + "%s", + "Could not process the request because the VPN connection is already being started."); + break; + case NM_VPN_SERVICE_STATE_STARTED: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, + "%s", + "Could not process the request because a VPN connection was already active."); + break; + case NM_VPN_SERVICE_STATE_STOPPING: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, + "%s", + "Could not process the request because the VPN connection is being stopped."); + break; + case NM_VPN_SERVICE_STATE_STOPPED: + case NM_VPN_SERVICE_STATE_INIT: + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING); + ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->connect (plugin, connection, err); + if (!ret) { + /* Stop the plugin from and idle handler so that the Connect + * method return gets sent before the STOP StateChanged signal. + */ + if (priv->fail_stop_id) + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = g_idle_add (fail_stop, plugin); + } + break; + + default: + g_assert_not_reached (); + break; + } + + return ret; +} + +void +nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin, + GHashTable *ip4_config) +{ + g_return_if_fail (NM_IS_VPN_PLUGIN (plugin)); + g_return_if_fail (ip4_config != NULL); + + g_signal_emit (plugin, signals[IP4_CONFIG], 0, ip4_config); + + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED); +} + + +static gboolean +impl_vpn_plugin_connect (NMVPNPlugin *plugin, + GHashTable *properties, + GError **error) +{ + NMConnection *connection; + gboolean success = FALSE; + + connection = nm_connection_new_from_hash (properties, error); + if (!connection) { + nm_warning ("%s: Invalid connection: '%s' / '%s' invalid: %d", + __func__, + g_type_name (nm_connection_lookup_setting_type_by_quark ((*error)->domain)), + (*error)->message, + (*error)->code); + } else { + success = nm_vpn_plugin_connect (plugin, connection, error); + g_object_unref (connection); + } + + return success; +} + +static gboolean +impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin, + GHashTable *properties, + char **setting_name, + GError **err) +{ + gboolean ret = FALSE; + NMConnection *connection; + char *sn = NULL; + GError *ns_err = NULL; + gboolean needed = FALSE; + GError *cnfh_err = NULL; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); + g_return_val_if_fail (properties != NULL, FALSE); + + connection = nm_connection_new_from_hash (properties, &cnfh_err); + if (!connection) { + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, + "The connection was invalid: '%s' / '%s' invalid: %d.", + g_type_name (nm_connection_lookup_setting_type_by_quark (cnfh_err->domain)), + cnfh_err->message, cnfh_err->code); + g_error_free (cnfh_err); + return FALSE; + } + + if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets) { + *setting_name = ""; + ret = TRUE; + goto out; + } + + needed = NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets (plugin, connection, &sn, &ns_err); + if (ns_err) { + *err = g_error_copy (ns_err); + g_error_free (ns_err); + goto out; + } + + ret = TRUE; + if (needed) { + g_assert (sn); + *setting_name = g_strdup (sn); + } else { + /* No secrets required */ + *setting_name = g_strdup (""); + } + +out: + return ret; +} + +static gboolean +impl_vpn_plugin_disconnect (NMVPNPlugin *plugin, + GError **err) +{ + return nm_vpn_plugin_disconnect (plugin, err); +} + +static gboolean +impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin, + GHashTable *config, + GError **err) +{ + nm_vpn_plugin_set_ip4_config (plugin, config); + + return TRUE; +} + +static gboolean +impl_vpn_plugin_set_failure (NMVPNPlugin *plugin, + char *reason, + GError **err) +{ + nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG); + + return TRUE; +} + +/*********************************************************************/ + +static void +sigterm_handler (int signum) +{ + g_slist_foreach (active_plugins, (GFunc) nm_vpn_plugin_emit_quit, NULL); +} + +static void +setup_unix_signal_handler (void) +{ + struct sigaction action; + sigset_t block_mask; + + action.sa_handler = sigterm_handler; + sigemptyset (&block_mask); + action.sa_mask = block_mask; + action.sa_flags = 0; + sigaction (SIGINT, &action, NULL); + sigaction (SIGTERM, &action, NULL); +} + +/*********************************************************************/ + +static void +one_plugin_destroyed (gpointer data, + GObject *object) +{ + active_plugins = g_slist_remove (active_plugins, object); +} + +static void +nm_vpn_plugin_init (NMVPNPlugin *plugin) +{ + active_plugins = g_slist_append (active_plugins, plugin); + g_object_weak_ref (G_OBJECT (plugin), + one_plugin_destroyed, + NULL); +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMVPNPlugin *plugin; + NMVPNPluginPrivate *priv; + DBusGConnection *connection; + DBusGProxy *proxy; + guint request_name_result; + GError *err = NULL; + + object = G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_VPN_PLUGIN_GET_PRIVATE (object); + if (!priv->dbus_service_name) + goto err; + + connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + if (!connection) + goto err; + + proxy = dbus_g_proxy_new_for_name (connection, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"); + + if (!dbus_g_proxy_call (proxy, "RequestName", &err, + G_TYPE_STRING, priv->dbus_service_name, + G_TYPE_UINT, 0, + G_TYPE_INVALID, + G_TYPE_UINT, &request_name_result, + G_TYPE_INVALID)) { + g_object_unref (proxy); + goto err; + } + + g_object_unref (proxy); + + dbus_g_connection_register_g_object (connection, + NM_VPN_DBUS_PLUGIN_PATH, + object); + + plugin = NM_VPN_PLUGIN (object); + + nm_vpn_plugin_set_connection (plugin, connection); + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_INIT); + + return object; + + err: + if (err) { + nm_warning ("%s", err->message); + g_error_free (err); + } + + if (object) + g_object_unref (object); + + return NULL; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_DBUS_SERVICE_NAME: + /* Construct-only */ + priv->dbus_service_name = g_strdup (g_value_get_string (value)); + break; + case PROP_STATE: + nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object), + (NMVPNServiceState) g_value_get_uint (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_DBUS_SERVICE_NAME: + g_value_set_string (value, priv->dbus_service_name); + break; + case PROP_STATE: + g_value_set_uint (value, nm_vpn_plugin_get_state (NM_VPN_PLUGIN (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMVPNPlugin *plugin = NM_VPN_PLUGIN (object); + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + NMVPNServiceState state; + GError *err = NULL; + + if (priv->disposed) { + G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + if (priv->fail_stop_id) + g_source_remove (priv->fail_stop_id); + + state = nm_vpn_plugin_get_state (plugin); + + if (state == NM_VPN_SERVICE_STATE_STARTED || + state == NM_VPN_SERVICE_STATE_STARTING) + nm_vpn_plugin_disconnect (plugin, &err); + + if (err) { + nm_warning ("%s", err->message); + g_error_free (err); + } + + G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMVPNPlugin *plugin = NM_VPN_PLUGIN (object); + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + + nm_vpn_plugin_set_connection (plugin, NULL); + g_free (priv->dbus_service_name); + + G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->finalize (object); +} + +static void +connect_timer_removed (gpointer data) +{ + NM_VPN_PLUGIN_GET_PRIVATE (data)->connect_timer = 0; +} + +static void +quit_timer_removed (gpointer data) +{ + NM_VPN_PLUGIN_GET_PRIVATE (data)->quit_timer = 0; +} + +static void +state_changed (NMVPNPlugin *plugin, NMVPNServiceState state) +{ + NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + + switch (state) { + case NM_VPN_SERVICE_STATE_STARTING: + /* Remove the quit timer. */ + if (priv->quit_timer) + g_source_remove (priv->quit_timer); + + if (priv->fail_stop_id) { + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = 0; + } + + /* Add a timer to make sure we do not wait indefinitely for the successful connect. */ + priv->connect_timer = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, + NM_VPN_PLUGIN_CONNECT_TIMER, + connect_timer_expired, + plugin, + connect_timer_removed); + break; + case NM_VPN_SERVICE_STATE_STOPPED: + priv->quit_timer = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, + NM_VPN_PLUGIN_QUIT_TIMER, + quit_timer_expired, + plugin, + quit_timer_removed); + break; + default: + /* Clean up all timers we might have set up. */ + if (priv->connect_timer) + g_source_remove (priv->connect_timer); + + if (priv->quit_timer) + g_source_remove (priv->quit_timer); + + if (priv->fail_stop_id) { + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = 0; + } + break; + } +} + +static void +nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (plugin_class); + + g_type_class_add_private (object_class, sizeof (NMVPNPluginPrivate)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (plugin_class), + &dbus_glib_nm_vpn_plugin_object_info); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + plugin_class->state_changed = state_changed; + + /* properties */ + g_object_class_install_property + (object_class, PROP_DBUS_SERVICE_NAME, + g_param_spec_string (NM_VPN_PLUGIN_DBUS_SERVICE_NAME, + "DBus service name", + "DBus service name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_uint (NM_VPN_PLUGIN_STATE, + "State", + "Current VPN service state", + NM_VPN_SERVICE_STATE_UNKNOWN, + NM_VPN_SERVICE_STATE_STOPPED, + NM_VPN_SERVICE_STATE_INIT, + G_PARAM_READWRITE)); + + /* signals */ + signals[STATE_CHANGED] = + g_signal_new ("state-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVPNPluginClass, state_changed), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[IP4_CONFIG] = + g_signal_new ("ip4-config", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVPNPluginClass, ip4_config), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + DBUS_TYPE_G_MAP_OF_VARIANT); + + signals[LOGIN_BANNER] = + g_signal_new ("login-banner", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVPNPluginClass, login_banner), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[FAILURE] = + g_signal_new ("failure", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVPNPluginClass, failure), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[QUIT] = + g_signal_new ("quit", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVPNPluginClass, quit), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, + G_TYPE_NONE); + + dbus_g_error_domain_register (NM_VPN_PLUGIN_ERROR, + NULL, + NM_TYPE_VPN_PLUGIN_ERROR); + + setup_unix_signal_handler (); +} |