diff options
author | Dan Williams <dcbw@redhat.com> | 2014-05-20 09:36:17 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2014-06-06 13:43:46 -0500 |
commit | e1ec6a51737be00ad98cd013059924bc68b1712b (patch) | |
tree | 6924ec89ca010f04743e6576f99e82b6b6bcea81 | |
parent | 27cb927d8fb870c360f5273549e2ee6a7639faa2 (diff) | |
download | NetworkManager-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.c | 106 | ||||
-rw-r--r-- | src/vpn-manager/nm-vpn-connection.h | 9 | ||||
-rw-r--r-- | src/vpn-manager/nm-vpn-manager.c | 2 | ||||
-rw-r--r-- | src/vpn-manager/nm-vpn-service.c | 9 |
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; } |