mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-08 12:40:36 +01:00
vpn: implement PRE_DOWN dispatcher actions (bgo #387832)
https://bugzilla.gnome.org/show_bug.cgi?id=387832
This commit is contained in:
parent
27cb927d8f
commit
e1ec6a5173
4 changed files with 77 additions and 49 deletions
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue