summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-05-20 09:36:17 -0500
committerDan Williams <dcbw@redhat.com>2014-06-06 13:43:46 -0500
commite1ec6a51737be00ad98cd013059924bc68b1712b (patch)
tree6924ec89ca010f04743e6576f99e82b6b6bcea81
parent27cb927d8fb870c360f5273549e2ee6a7639faa2 (diff)
downloadNetworkManager-e1ec6a51737be00ad98cd013059924bc68b1712b.tar.gz
vpn: implement PRE_DOWN dispatcher actions (bgo #387832)
https://bugzilla.gnome.org/show_bug.cgi?id=387832
-rw-r--r--src/vpn-manager/nm-vpn-connection.c106
-rw-r--r--src/vpn-manager/nm-vpn-connection.h9
-rw-r--r--src/vpn-manager/nm-vpn-manager.c2
-rw-r--r--src/vpn-manager/nm-vpn-service.c9
4 files changed, 77 insertions, 49 deletions
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index 3d43c3ece8..052ebfe4b1 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -84,7 +84,7 @@ typedef struct {
char *username;
VpnState vpn_state;
- guint deactivating_idle_id;
+ guint dispatcher_id;
NMVPNConnectionStateReason failure_reason;
DBusGProxy *proxy;
@@ -137,7 +137,8 @@ static void plugin_interactive_secrets_required (DBusGProxy *proxy,
static void _set_vpn_state (NMVPNConnection *connection,
VpnState vpn_state,
- NMVPNConnectionStateReason reason);
+ NMVPNConnectionStateReason reason,
+ gboolean quitting);
/*********************************************************************/
@@ -245,32 +246,32 @@ vpn_cleanup (NMVPNConnection *connection, NMDevice *parent_dev)
nm_connection_clear_secrets (priv->connection);
}
-static gboolean
-deactivating_to_disconnected (gpointer user_data)
+static void
+dispatcher_pre_down_done (guint call_id, gpointer user_data)
{
NMVPNConnection *self = NM_VPN_CONNECTION (user_data);
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
- priv->deactivating_idle_id = 0;
- _set_vpn_state (self, STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_NONE);
- return G_SOURCE_REMOVE;
+ priv->dispatcher_id = 0;
+ _set_vpn_state (self, STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
}
static void
-clear_deactivating_idle (NMVPNConnection *self)
+dispatcher_cleanup (NMVPNConnection *self)
{
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
- if (priv->deactivating_idle_id) {
- g_source_remove (priv->deactivating_idle_id);
- priv->deactivating_idle_id = 0;
+ if (priv->dispatcher_id) {
+ nm_dispatcher_call_cancel (priv->dispatcher_id);
+ priv->dispatcher_id = 0;
}
}
static void
_set_vpn_state (NMVPNConnection *connection,
VpnState vpn_state,
- NMVPNConnectionStateReason reason)
+ NMVPNConnectionStateReason reason,
+ gboolean quitting)
{
NMVPNConnectionPrivate *priv;
VpnState old_vpn_state;
@@ -303,7 +304,7 @@ _set_vpn_state (NMVPNConnection *connection,
priv->secrets_id = 0;
}
- clear_deactivating_idle (connection);
+ dispatcher_cleanup (connection);
/* The connection gets destroyed by the VPN manager when it enters the
* disconnected/failed state, but we need to keep it around for a bit
@@ -345,7 +346,27 @@ _set_vpn_state (NMVPNConnection *connection,
NULL);
break;
case STATE_DEACTIVATING:
- priv->deactivating_idle_id = g_idle_add (deactivating_to_disconnected, connection);
+ if (quitting) {
+ nm_dispatcher_call_vpn_sync (DISPATCHER_ACTION_VPN_PRE_DOWN,
+ priv->connection,
+ parent_dev,
+ priv->ip_iface,
+ priv->ip4_config,
+ priv->ip6_config);
+ } else {
+ if (!nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_PRE_DOWN,
+ priv->connection,
+ parent_dev,
+ priv->ip_iface,
+ priv->ip4_config,
+ priv->ip6_config,
+ dispatcher_pre_down_done,
+ connection,
+ &priv->dispatcher_id)) {
+ /* Just proceed on errors */
+ dispatcher_pre_down_done (0, connection);
+ }
+ }
break;
case STATE_FAILED:
case STATE_DISCONNECTED:
@@ -386,11 +407,13 @@ device_state_changed (NMActiveConnection *active,
if (new_state <= NM_DEVICE_STATE_DISCONNECTED) {
_set_vpn_state (NM_VPN_CONNECTION (active),
STATE_DISCONNECTED,
- NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
+ NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED,
+ FALSE);
} else if (new_state == NM_DEVICE_STATE_FAILED) {
_set_vpn_state (NM_VPN_CONNECTION (active),
STATE_FAILED,
- NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
+ NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED,
+ FALSE);
}
/* FIXME: map device DEACTIVATING state to VPN DEACTIVATING state and
@@ -665,7 +688,7 @@ plugin_state_changed (DBusGProxy *proxy,
case STATE_ACTIVATED:
nm_log_info (LOGD_VPN, "VPN plugin state change reason: %s (%d)",
vpn_reason_to_string (priv->failure_reason), priv->failure_reason);
- _set_vpn_state (connection, STATE_FAILED, priv->failure_reason);
+ _set_vpn_state (connection, STATE_FAILED, priv->failure_reason, FALSE);
/* Reset the failure reason */
priv->failure_reason = NM_VPN_CONNECTION_STATE_REASON_UNKNOWN;
@@ -836,7 +859,7 @@ nm_vpn_connection_apply_config (NMVPNConnection *connection)
nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.",
nm_connection_get_id (priv->connection));
- _set_vpn_state (connection, STATE_ACTIVATED, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_ACTIVATED, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
return TRUE;
}
@@ -876,7 +899,7 @@ nm_vpn_connection_config_maybe_complete (NMVPNConnection *connection,
nm_log_warn (LOGD_VPN, "VPN connection '%s' did not receive valid IP config information.",
nm_connection_get_id (priv->connection));
- _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID);
+ _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE);
}
#define LOG_INVALID_ARG(property) \
@@ -971,7 +994,7 @@ nm_vpn_connection_config_get (DBusGProxy *proxy,
nm_connection_get_id (priv->connection));
if (priv->vpn_state == STATE_CONNECT)
- _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
if (!process_generic_config (connection, config_hash))
return;
@@ -1025,7 +1048,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
int i;
if (priv->vpn_state == STATE_CONNECT)
- _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
if (priv->has_ip4) {
nm_log_info (LOGD_VPN, "VPN connection '%s' (IP4 Config Get) reply received.",
@@ -1181,7 +1204,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy,
nm_connection_get_id (priv->connection));
if (priv->vpn_state == STATE_CONNECT)
- _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
if (g_hash_table_size (config_hash) == 0) {
priv->has_ip6 = FALSE;
@@ -1322,7 +1345,7 @@ connect_timeout_cb (gpointer user_data)
priv->vpn_state == STATE_IP_CONFIG_GET) {
nm_log_warn (LOGD_VPN, "VPN connection '%s' connect timeout exceeded.",
nm_connection_get_id (priv->connection));
- _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT);
+ _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT, FALSE);
}
return FALSE;
@@ -1359,7 +1382,7 @@ connect_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
nm_log_warn (LOGD_VPN, "VPN connection '%s' failed to connect: '%s'.",
nm_connection_get_id (priv->connection), err->message);
g_error_free (err);
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, FALSE);
}
static void
@@ -1388,7 +1411,7 @@ connect_interactive_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data
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);
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, FALSE);
}
}
@@ -1483,7 +1506,7 @@ really_activate (NMVPNConnection *connection, const char *username)
g_object_unref (agent_mgr);
g_hash_table_destroy (details);
- _set_vpn_state (connection, STATE_CONNECT, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_CONNECT, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
}
void
@@ -1496,7 +1519,7 @@ nm_vpn_connection_activate (NMVPNConnection *connection)
priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
- _set_vpn_state (connection, STATE_PREPARE, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_PREPARE, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ());
priv->proxy = dbus_g_proxy_new_for_name (bus,
@@ -1522,7 +1545,7 @@ nm_vpn_connection_activate (NMVPNConnection *connection)
G_CALLBACK (plugin_interactive_secrets_required),
connection, NULL);
- _set_vpn_state (connection, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
/* Kick off the secrets requests; first we get existing system secrets
* and ask the plugin if these are sufficient, next we get all existing
@@ -1605,18 +1628,19 @@ nm_vpn_connection_get_ip6_internal_gateway (NMVPNConnection *connection)
}
void
-nm_vpn_connection_stop (NMVPNConnection *connection,
- gboolean fail,
- NMVPNConnectionStateReason reason)
+nm_vpn_connection_disconnect (NMVPNConnection *connection,
+ NMVPNConnectionStateReason reason,
+ gboolean quitting)
{
g_return_if_fail (NM_IS_VPN_CONNECTION (connection));
- _set_vpn_state (connection, fail ? STATE_FAILED : STATE_DISCONNECTED, reason);
+ _set_vpn_state (connection, STATE_DISCONNECTED, reason, quitting);
}
gboolean
nm_vpn_connection_deactivate (NMVPNConnection *connection,
- NMVPNConnectionStateReason reason)
+ NMVPNConnectionStateReason reason,
+ gboolean quitting)
{
NMVPNConnectionPrivate *priv;
gboolean success = FALSE;
@@ -1625,7 +1649,7 @@ nm_vpn_connection_deactivate (NMVPNConnection *connection,
priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
if (priv->vpn_state > STATE_UNKNOWN && priv->vpn_state <= STATE_DEACTIVATING) {
- _set_vpn_state (connection, STATE_DEACTIVATING, reason);
+ _set_vpn_state (connection, STATE_DEACTIVATING, reason, quitting);
success = TRUE;
}
return success;
@@ -1651,7 +1675,7 @@ plugin_need_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_dat
priv->secrets_idx + 1,
g_quark_to_string (error->domain),
error->message);
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE);
g_error_free (error);
return;
}
@@ -1663,7 +1687,7 @@ plugin_need_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_dat
nm_log_err (LOGD_VPN, "(%s/%s) final secrets request failed to provide sufficient secrets",
nm_connection_get_uuid (priv->connection),
nm_connection_get_id (priv->connection));
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE);
} else {
nm_log_dbg (LOGD_VPN, "(%s/%s) service indicated additional secrets required",
nm_connection_get_uuid (priv->connection),
@@ -1695,7 +1719,7 @@ plugin_new_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data
nm_connection_get_id (priv->connection),
g_quark_to_string (error->domain),
error->message);
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE);
g_error_free (error);
}
}
@@ -1720,7 +1744,7 @@ get_secrets_cb (NMSettingsConnection *connection,
if (error) {
nm_log_err (LOGD_VPN, "Failed to request VPN secrets #%d: (%d) %s",
priv->secrets_idx + 1, error->code, error->message);
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE);
} else {
/* Cache the username for later */
if (agent_username) {
@@ -1804,7 +1828,7 @@ get_secrets (NMVPNConnection *self,
nm_log_err (LOGD_VPN, "failed to request VPN secrets #%d: (%d) %s",
priv->secrets_idx + 1, error->code, error->message);
}
- _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS);
+ _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE);
g_clear_error (&error);
}
}
@@ -1828,7 +1852,7 @@ plugin_interactive_secrets_required (DBusGProxy *proxy,
priv->vpn_state == STATE_NEED_AUTH);
priv->secrets_idx = SECRETS_REQ_INTERACTIVE;
- _set_vpn_state (connection, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE);
+ _set_vpn_state (connection, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
/* Copy hints and add message to the end */
hints = g_malloc0 (sizeof (char *) * (secrets_len + 2));
@@ -1878,7 +1902,7 @@ dispose (GObject *object)
priv->connect_timeout = 0;
}
- clear_deactivating_idle (NM_VPN_CONNECTION (object));
+ dispatcher_cleanup (NM_VPN_CONNECTION (object));
if (priv->secrets_id) {
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection),
diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h
index e5563b0000..c9c88cda14 100644
--- a/src/vpn-manager/nm-vpn-connection.h
+++ b/src/vpn-manager/nm-vpn-connection.h
@@ -76,10 +76,11 @@ NMVPNConnectionState nm_vpn_connection_get_vpn_state (NMVPNConnection *connect
const char * nm_vpn_connection_get_banner (NMVPNConnection *connection);
gboolean nm_vpn_connection_deactivate (NMVPNConnection *connection,
- NMVPNConnectionStateReason reason);
-void nm_vpn_connection_stop (NMVPNConnection *connection,
- gboolean fail,
- NMVPNConnectionStateReason reason);
+ NMVPNConnectionStateReason reason,
+ gboolean quitting);
+void nm_vpn_connection_disconnect (NMVPNConnection *connection,
+ NMVPNConnectionStateReason reason,
+ gboolean quitting);
NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connection);
NMIP6Config * nm_vpn_connection_get_ip6_config (NMVPNConnection *connection);
diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c
index 00ce4e8f52..5550d4d6c6 100644
--- a/src/vpn-manager/nm-vpn-manager.c
+++ b/src/vpn-manager/nm-vpn-manager.c
@@ -123,7 +123,7 @@ nm_vpn_manager_deactivate_connection (NMVPNManager *self,
NMVPNConnection *connection,
NMVPNConnectionStateReason reason)
{
- return nm_vpn_connection_deactivate (connection, reason);
+ return nm_vpn_connection_deactivate (connection, reason, FALSE);
}
static void
diff --git a/src/vpn-manager/nm-vpn-service.c b/src/vpn-manager/nm-vpn-service.c
index 3752797fb8..9eb6b96824 100644
--- a/src/vpn-manager/nm-vpn-service.c
+++ b/src/vpn-manager/nm-vpn-service.c
@@ -157,8 +157,11 @@ nm_vpn_service_stop_connections (NMVPNService *service,
NMVPNConnection *vpn = NM_VPN_CONNECTION (iter->data);
g_signal_handlers_disconnect_by_func (vpn, G_CALLBACK (connection_vpn_state_changed), service);
- /* Quitting terminates the VPN cleanly, otherwise failure is assumed */
- nm_vpn_connection_stop (vpn, quitting ? FALSE : TRUE, reason);
+ if (quitting) {
+ /* Deactivate to allow pre-down before disconnecting */
+ nm_vpn_connection_deactivate (vpn, reason, quitting);
+ }
+ nm_vpn_connection_disconnect (vpn, reason, quitting);
g_object_unref (vpn);
}
g_clear_pointer (&priv->pending, g_slist_free);
@@ -292,7 +295,7 @@ nm_vpn_service_activate (NMVPNService *service,
* connection_vpn_state_changed().
*/
if (priv->active) {
- nm_vpn_connection_deactivate (priv->active, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED);
+ nm_vpn_connection_deactivate (priv->active, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED, FALSE);
return TRUE;
}