This fixes following scenario:
- user tries to connect to a VPN
- VPN requests some additional data via agent interface
- user cancels the agent request
- VPN connection is terminated
- VPN service goes back to idle
- user tries to connect to a VPN again
- VPN does not ask anything from the user (this is the issue)
- user cannot connect to VPN

The reason for the problem was that the VPN plugin state
was not updated properly if the VPN connection attempt failed.

Reported by Jaakko Hannikainen.
---
 vpn/plugins/vpn.c  | 27 +++++++++++++++++++++++++++
 vpn/vpn-provider.c |  3 +++
 vpn/vpn-provider.h |  2 ++
 3 files changed, 32 insertions(+)

diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c
index b438d06..60954be 100644
--- a/vpn/plugins/vpn.c
+++ b/vpn/plugins/vpn.c
@@ -195,6 +195,32 @@ int vpn_set_ifname(struct vpn_provider *provider, const 
char *ifname)
        return 0;
 }
 
+static int vpn_set_state(struct vpn_provider *provider,
+                                               enum vpn_provider_state state)
+{
+       struct vpn_data *data = vpn_provider_get_data(provider);
+
+       switch (state) {
+       case VPN_PROVIDER_STATE_UNKNOWN:
+               return -EINVAL;
+       case VPN_PROVIDER_STATE_IDLE:
+               data->state = VPN_STATE_IDLE;
+               break;
+       case VPN_PROVIDER_STATE_CONNECT:
+       case VPN_PROVIDER_STATE_READY:
+               data->state = VPN_STATE_CONNECT;
+               break;
+       case VPN_PROVIDER_STATE_DISCONNECT:
+               data->state = VPN_STATE_DISCONNECT;
+               break;
+       case VPN_PROVIDER_STATE_FAILURE:
+               data->state = VPN_STATE_FAILURE;
+               break;
+       }
+
+       return 0;
+}
+
 static void vpn_newlink(unsigned flags, unsigned change, void *user_data)
 {
        struct vpn_provider *provider = user_data;
@@ -572,6 +598,7 @@ int vpn_register(const char *name, struct vpn_driver 
*vpn_driver,
        data->provider_driver.probe = vpn_probe;
        data->provider_driver.remove = vpn_remove;
        data->provider_driver.save = vpn_save;
+       data->provider_driver.set_state = vpn_set_state;
 
        if (!driver_hash)
                driver_hash = g_hash_table_new_full(g_str_hash,
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index a8d05bf..afd7ca6 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -1587,6 +1587,9 @@ int vpn_provider_indicate_error(struct vpn_provider 
*provider,
                break;
        }
 
+       if (provider->driver && provider->driver->set_state)
+               provider->driver->set_state(provider, provider->state);
+
        return 0;
 }
 
diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h
index 8105d7f..bdc5f5c 100644
--- a/vpn/vpn-provider.h
+++ b/vpn/vpn-provider.h
@@ -132,6 +132,8 @@ struct vpn_provider_driver {
                        void *user_data);
        int (*disconnect) (struct vpn_provider *provider);
        int (*save) (struct vpn_provider *provider, GKeyFile *keyfile);
+       int (*set_state)(struct vpn_provider *provider,
+                                               enum vpn_provider_state state);
 };
 
 int vpn_provider_driver_register(struct vpn_provider_driver *driver);
-- 
2.1.0

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to