From 9dff830692c8ff0fe69291e4bc882e4060d77542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Thu, 26 Sep 2013 10:19:33 +0200 Subject: [PATCH] vpn: fix connecting to VPN (bgo #708255) The ConnectInteractive() -> Connect() fallback code doesn't work, because _connect_internal() changes the state to NM_VPN_SERVICE_STATE_STARTING before checking if it can implement ConnectInteractive(), and then when the Connect() call comes in, the VPN is not in STOPPED or INIT, so it returns an error. The commit moves setting state to STARTING after the ConnectInteractive() check availability, in the plugin. We introduce new plugin error and set it when the the plugin does not implement ConnectInteractive(). NetworkManager uses this error for ConnectInteractive() -> Connect() fallback. https://bugzilla.gnome.org/show_bug.cgi?id=708255 --- include/NetworkManagerVPN.h | 1 + introspection/nm-vpn-plugin.xml | 2 ++ introspection/vpn-errors.xml | 6 ++++++ libnm-glib/nm-vpn-plugin.c | 7 ++++--- libnm-glib/nm-vpn-plugin.h | 24 ++++++++++++++---------- src/vpn-manager/nm-vpn-connection.c | 19 ++++++++++++++----- 6 files changed, 41 insertions(+), 18 deletions(-) diff --git a/include/NetworkManagerVPN.h b/include/NetworkManagerVPN.h index 6e654b3a7a..c5e6d3a456 100644 --- a/include/NetworkManagerVPN.h +++ b/include/NetworkManagerVPN.h @@ -47,6 +47,7 @@ #define NM_DBUS_VPN_ALREADY_STOPPED "AlreadyStopped" #define NM_DBUS_VPN_WRONG_STATE "WrongState" #define NM_DBUS_VPN_BAD_ARGUMENTS "BadArguments" +#define NM_DBUS_VPN_INTERACTIVE_NOT_SUPPORTED "InteractiveNotSupported" /* diff --git a/introspection/nm-vpn-plugin.xml b/introspection/nm-vpn-plugin.xml index 79081f7b2e..07397c2b97 100644 --- a/introspection/nm-vpn-plugin.xml +++ b/introspection/nm-vpn-plugin.xml @@ -52,6 +52,7 @@ + @@ -191,6 +192,7 @@ + diff --git a/introspection/vpn-errors.xml b/introspection/vpn-errors.xml index 0dba7e6fb9..c5bf73d972 100644 --- a/introspection/vpn-errors.xml +++ b/introspection/vpn-errors.xml @@ -28,5 +28,11 @@ The request could not be processed because the VPN connection settings were invalid. + + + The request could not be processed because the plugin does not support + interactive operations, such as ConnectInteractive() or NewSecrets(). + + diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c index 1894c966c8..4289267f95 100644 --- a/libnm-glib/nm-vpn-plugin.c +++ b/libnm-glib/nm-vpn-plugin.c @@ -457,15 +457,16 @@ _connect_generic (NMVPNPlugin *plugin, return FALSE; } - nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING); priv->interactive = FALSE; if (details && !vpn_class->connect_interactive) { - g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, + g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, "Plugin does not implement ConnectInteractive()"); return FALSE; } + nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING); + if (details) { priv->interactive = TRUE; success = vpn_class->connect_interactive (plugin, connection, details, error); @@ -586,7 +587,7 @@ impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin, } if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets) { - g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, + g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, "Could not accept new secrets: plugin cannot process interactive secrets"); g_object_unref (connection); return FALSE; diff --git a/libnm-glib/nm-vpn-plugin.h b/libnm-glib/nm-vpn-plugin.h index dc237d5245..0c037e45a3 100644 --- a/libnm-glib/nm-vpn-plugin.h +++ b/libnm-glib/nm-vpn-plugin.h @@ -18,7 +18,7 @@ * Boston, MA 02110-1301 USA. * * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. */ #ifndef NM_VPN_PLUGIN_H @@ -63,19 +63,23 @@ G_BEGIN_DECLS * @NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID: the operation could not be performed * because the connection was invalid. Usually means that the connection's * VPN setting was missing some required data item or secret. + * @NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED: the operation could not be + * performed as the plugin does not support interactive operations, such as + * ConnectInteractive() or NewSecrets() * * Returned by the VPN service plugin to indicate errors. **/ typedef enum { - NM_VPN_PLUGIN_ERROR_GENERAL, /*< nick=General >*/ - NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, /*< nick=StartingInProgress >*/ - NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, /*< nick=AlreadyStarted >*/ - NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, /*< nick=StoppingInProgress >*/ - NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, /*< nick=AlreadyStopped >*/ - NM_VPN_PLUGIN_ERROR_WRONG_STATE, /*< nick=WrongState >*/ - NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, /*< nick=BadArguments >*/ - NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, /*< nick=LaunchFailed >*/ - NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_VPN_PLUGIN_ERROR_GENERAL, /*< nick=General >*/ + NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, /*< nick=StartingInProgress >*/ + NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, /*< nick=AlreadyStarted >*/ + NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, /*< nick=StoppingInProgress >*/ + NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, /*< nick=AlreadyStopped >*/ + NM_VPN_PLUGIN_ERROR_WRONG_STATE, /*< nick=WrongState >*/ + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, /*< nick=BadArguments >*/ + NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, /*< nick=LaunchFailed >*/ + NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED /*< nick=InteractiveNotSupported >*/ } NMVPNPluginError; #define NM_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_quark ()) diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index a223ee3127..a42613a8b8 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -1181,11 +1181,20 @@ connect_interactive_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data return; } - /* Fall back to Connect() */ - dbus_g_proxy_begin_call (priv->proxy, "Connect", - connect_cb, self, NULL, - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, priv->connect_hash, - G_TYPE_INVALID); + if (dbus_g_error_has_name (err, "org.freedesktop.NetworkManager.VPN.Plugin.InteractiveNotSupported")) { + /* Fall back to Connect() */ + dbus_g_proxy_begin_call (priv->proxy, "Connect", + connect_cb, self, NULL, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, priv->connect_hash, + G_TYPE_INVALID); + } else { + nm_log_warn (LOGD_VPN, "VPN connection '%s' failed to connect interactively: '%s'.", + nm_connection_get_id (priv->connection), err->message); + g_error_free (err); + nm_vpn_connection_set_vpn_state (self, + NM_VPN_CONNECTION_STATE_FAILED, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED); + } } /* Add a username to a hashed connection */