cli/connections: fail the activation when the active connection disappears
Relying solemnly on device or active connection state is unreliable.
This commit is contained in:
@@ -1963,6 +1963,14 @@ find_device_for_connection (NmCli *nmc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NmCli *nmc;
|
||||||
|
NMDevice *device;
|
||||||
|
NMActiveConnection *active;
|
||||||
|
} ActivateConnectionInfo;
|
||||||
|
|
||||||
|
static void activate_connection_info_finish (ActivateConnectionInfo *info);
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
vpn_connection_state_reason_to_string (NMVpnConnectionStateReason reason)
|
vpn_connection_state_reason_to_string (NMVpnConnectionStateReason reason)
|
||||||
{
|
{
|
||||||
@@ -1997,9 +2005,9 @@ vpn_connection_state_reason_to_string (NMVpnConnectionStateReason reason)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
device_state_cb (NMDevice *device, GParamSpec *pspec, ActivateConnectionInfo *info)
|
||||||
{
|
{
|
||||||
NmCli *nmc = (NmCli *) user_data;
|
NmCli *nmc = info->nmc;
|
||||||
NMActiveConnection *active;
|
NMActiveConnection *active;
|
||||||
NMDeviceState state;
|
NMDeviceState state;
|
||||||
NMActiveConnectionState ac_state;
|
NMActiveConnectionState ac_state;
|
||||||
@@ -2014,7 +2022,7 @@ device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
|||||||
nmc_terminal_erase_line ();
|
nmc_terminal_erase_line ();
|
||||||
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
nm_object_get_path (NM_OBJECT (active)));
|
||||||
quit ();
|
activate_connection_info_finish (info);
|
||||||
} else if ( ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
} else if ( ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
||||||
&& state >= NM_DEVICE_STATE_IP_CONFIG
|
&& state >= NM_DEVICE_STATE_IP_CONFIG
|
||||||
&& state <= NM_DEVICE_STATE_ACTIVATED) {
|
&& state <= NM_DEVICE_STATE_ACTIVATED) {
|
||||||
@@ -2022,24 +2030,26 @@ device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
|||||||
nmc_terminal_erase_line ();
|
nmc_terminal_erase_line ();
|
||||||
g_print (_("Connection successfully activated (master waiting for slaves) (D-Bus active path: %s)\n"),
|
g_print (_("Connection successfully activated (master waiting for slaves) (D-Bus active path: %s)\n"),
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
nm_object_get_path (NM_OBJECT (active)));
|
||||||
quit ();
|
activate_connection_info_finish (info);
|
||||||
} else if ( ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
|
||||||
&& state == NM_DEVICE_STATE_FAILED) {
|
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
|
||||||
nmc_terminal_erase_line ();
|
|
||||||
g_print (_("Error: Connection activation failed.\n"));
|
|
||||||
quit ();
|
|
||||||
} else if (active && ac_state != NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
|
||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed."));
|
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
||||||
quit ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, gpointer user_data)
|
active_connection_removed_cb (NMClient *client, NMActiveConnection *active, ActivateConnectionInfo *info)
|
||||||
{
|
{
|
||||||
NmCli *nmc = (NmCli *) user_data;
|
NmCli *nmc = info->nmc;
|
||||||
|
|
||||||
|
if (active == info->active) {
|
||||||
|
g_string_printf (nmc->return_text, _("Error: Connection activation failed."));
|
||||||
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
|
activate_connection_info_finish (info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, ActivateConnectionInfo *info)
|
||||||
|
{
|
||||||
|
NmCli *nmc = info->nmc;
|
||||||
NMActiveConnectionState state;
|
NMActiveConnectionState state;
|
||||||
|
|
||||||
state = nm_active_connection_get_state (active);
|
state = nm_active_connection_get_state (active);
|
||||||
@@ -2049,13 +2059,7 @@ active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, gpoin
|
|||||||
nmc_terminal_erase_line ();
|
nmc_terminal_erase_line ();
|
||||||
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
nm_object_get_path (NM_OBJECT (active)));
|
||||||
g_object_unref (active);
|
activate_connection_info_finish (info);
|
||||||
quit ();
|
|
||||||
} else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
|
|
||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed."));
|
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
||||||
g_object_unref (active);
|
|
||||||
quit ();
|
|
||||||
} else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
} else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
||||||
/* activating master connection does not automatically activate any slaves, so their
|
/* activating master connection does not automatically activate any slaves, so their
|
||||||
* active connection state will not progress beyond ACTIVATING state.
|
* active connection state will not progress beyond ACTIVATING state.
|
||||||
@@ -2076,10 +2080,8 @@ active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, gpoin
|
|||||||
&& ( NM_IS_DEVICE_BOND (device)
|
&& ( NM_IS_DEVICE_BOND (device)
|
||||||
|| NM_IS_DEVICE_TEAM (device)
|
|| NM_IS_DEVICE_TEAM (device)
|
||||||
|| NM_IS_DEVICE_BRIDGE (device))) {
|
|| NM_IS_DEVICE_BRIDGE (device))) {
|
||||||
g_signal_handlers_disconnect_by_func (active, G_CALLBACK (active_connection_state_cb), nmc);
|
g_signal_connect (device, "notify::" NM_DEVICE_STATE, G_CALLBACK (device_state_cb), info);
|
||||||
g_signal_connect (device, "notify::" NM_DEVICE_STATE, G_CALLBACK (device_state_cb), nmc);
|
device_state_cb (device, NULL, info);
|
||||||
|
|
||||||
device_state_cb (device, NULL, nmc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2088,9 +2090,9 @@ static void
|
|||||||
vpn_connection_state_cb (NMVpnConnection *vpn,
|
vpn_connection_state_cb (NMVpnConnection *vpn,
|
||||||
NMVpnConnectionState state,
|
NMVpnConnectionState state,
|
||||||
NMVpnConnectionStateReason reason,
|
NMVpnConnectionStateReason reason,
|
||||||
gpointer user_data)
|
ActivateConnectionInfo *info)
|
||||||
{
|
{
|
||||||
NmCli *nmc = (NmCli *) user_data;
|
NmCli *nmc = info->nmc;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case NM_VPN_CONNECTION_STATE_PREPARE:
|
case NM_VPN_CONNECTION_STATE_PREPARE:
|
||||||
@@ -2105,8 +2107,7 @@ vpn_connection_state_cb (NMVpnConnection *vpn,
|
|||||||
nmc_terminal_erase_line ();
|
nmc_terminal_erase_line ();
|
||||||
g_print (_("VPN connection successfully activated (D-Bus active path: %s)\n"),
|
g_print (_("VPN connection successfully activated (D-Bus active path: %s)\n"),
|
||||||
nm_object_get_path (NM_OBJECT (vpn)));
|
nm_object_get_path (NM_OBJECT (vpn)));
|
||||||
g_object_unref (vpn);
|
activate_connection_info_finish (info);
|
||||||
quit ();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NM_VPN_CONNECTION_STATE_FAILED:
|
case NM_VPN_CONNECTION_STATE_FAILED:
|
||||||
@@ -2114,8 +2115,7 @@ vpn_connection_state_cb (NMVpnConnection *vpn,
|
|||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s."),
|
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s."),
|
||||||
vpn_connection_state_reason_to_string (reason));
|
vpn_connection_state_reason_to_string (reason));
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
g_object_unref (vpn);
|
activate_connection_info_finish (info);
|
||||||
quit ();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -2126,13 +2126,14 @@ vpn_connection_state_cb (NMVpnConnection *vpn,
|
|||||||
static gboolean
|
static gboolean
|
||||||
timeout_cb (gpointer user_data)
|
timeout_cb (gpointer user_data)
|
||||||
{
|
{
|
||||||
/* Time expired -> exit nmcli */
|
ActivateConnectionInfo *info = user_data;
|
||||||
|
NmCli *nmc = info->nmc;
|
||||||
|
|
||||||
NmCli *nmc = (NmCli *) user_data;
|
/* Time expired -> exit nmcli */
|
||||||
|
|
||||||
g_string_printf (nmc->return_text, _("Error: Timeout %d sec expired."), nmc->timeout);
|
g_string_printf (nmc->return_text, _("Error: Timeout %d sec expired."), nmc->timeout);
|
||||||
nmc->return_value = NMC_RESULT_ERROR_TIMEOUT_EXPIRED;
|
nmc->return_value = NMC_RESULT_ERROR_TIMEOUT_EXPIRED;
|
||||||
quit ();
|
activate_connection_info_finish (info);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2171,10 +2172,24 @@ progress_vpn_cb (gpointer user_data)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
static void
|
||||||
NmCli *nmc;
|
activate_connection_info_finish (ActivateConnectionInfo *info)
|
||||||
NMDevice *device;
|
{
|
||||||
} ActivateConnectionInfo;
|
if (info->device)
|
||||||
|
g_signal_handlers_disconnect_by_func (info->device, G_CALLBACK (device_state_cb), info);
|
||||||
|
if (info->active) {
|
||||||
|
if (NM_IS_VPN_CONNECTION (info->active))
|
||||||
|
g_signal_handlers_disconnect_by_func (info->active, G_CALLBACK (vpn_connection_state_cb), info);
|
||||||
|
else
|
||||||
|
g_signal_handlers_disconnect_by_func (info->active, G_CALLBACK (active_connection_state_cb), info);
|
||||||
|
g_object_unref (info->active);
|
||||||
|
|
||||||
|
}
|
||||||
|
g_signal_handlers_disconnect_by_func (info->nmc->client, G_CALLBACK (active_connection_removed_cb), info);
|
||||||
|
|
||||||
|
g_free (info);
|
||||||
|
quit ();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_data)
|
activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_data)
|
||||||
@@ -2187,14 +2202,14 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
|
|||||||
const GPtrArray *ac_devs;
|
const GPtrArray *ac_devs;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error);
|
info->active = active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
|
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
|
||||||
error->message);
|
error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
quit ();
|
activate_connection_info_finish (info);
|
||||||
} else {
|
} else {
|
||||||
state = nm_active_connection_get_state (active);
|
state = nm_active_connection_get_state (active);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
@@ -2211,12 +2226,11 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
|
|||||||
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
nm_object_get_path (NM_OBJECT (active)));
|
||||||
}
|
}
|
||||||
g_object_unref (active);
|
activate_connection_info_finish (info);
|
||||||
quit ();
|
|
||||||
} else {
|
} else {
|
||||||
if (NM_IS_VPN_CONNECTION (active)) {
|
if (NM_IS_VPN_CONNECTION (active)) {
|
||||||
/* Monitor VPN state */
|
/* Monitor VPN state */
|
||||||
g_signal_connect (G_OBJECT (active), "vpn-state-changed", G_CALLBACK (vpn_connection_state_cb), nmc);
|
g_signal_connect (G_OBJECT (active), "vpn-state-changed", G_CALLBACK (vpn_connection_state_cb), info);
|
||||||
|
|
||||||
/* Start progress indication showing VPN states */
|
/* Start progress indication showing VPN states */
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
||||||
@@ -2225,8 +2239,8 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
|
|||||||
progress_id = g_timeout_add (120, progress_vpn_cb, NM_VPN_CONNECTION (active));
|
progress_id = g_timeout_add (120, progress_vpn_cb, NM_VPN_CONNECTION (active));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_signal_connect (active, "notify::state", G_CALLBACK (active_connection_state_cb), nmc);
|
g_signal_connect (active, "notify::state", G_CALLBACK (active_connection_state_cb), info);
|
||||||
active_connection_state_cb (active, NULL, nmc);
|
active_connection_state_cb (active, NULL, info);
|
||||||
|
|
||||||
/* Start progress indication showing device states */
|
/* Start progress indication showing device states */
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
||||||
@@ -2237,10 +2251,13 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Start timer not to loop forever when signals are not emitted */
|
/* Start timer not to loop forever when signals are not emitted */
|
||||||
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
|
g_timeout_add_seconds (nmc->timeout, timeout_cb, info);
|
||||||
|
|
||||||
|
/* Fail when the active connection goes away. */
|
||||||
|
g_signal_connect (nmc->client, NM_CLIENT_ACTIVE_CONNECTION_REMOVED,
|
||||||
|
G_CALLBACK (active_connection_removed_cb), info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_free (info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user