If the IP address changes when VPN restarts, then we handle that by
clearing the old address and setting the routes properly.
---
 vpn/plugins/vpn.c  | 25 +++++++++++++++++++++++++
 vpn/vpn-provider.c | 36 +++++++++++++++++++++++++++++-------
 2 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c
index 080086d..a1c5f18 100644
--- a/vpn/plugins/vpn.c
+++ b/vpn/plugins/vpn.c
@@ -245,6 +245,31 @@ static DBusMessage *vpn_notify(struct connman_task *task,
        switch (state) {
        case VPN_STATE_CONNECT:
        case VPN_STATE_READY:
+               if (data->state == VPN_STATE_READY) {
+                       /*
+                        * This is the restart case, in which case we must
+                        * just set the IP address.
+                        *
+                        * We need to remove first the old address, just
+                        * replacing the old address will not work as expected
+                        * because the old address will linger in the interface
+                        * and not disapper so the clearing is needed here.
+                        *
+                        * Also the state must change, otherwise the routes
+                        * will not be set properly.
+                        */
+                       vpn_provider_set_state(provider,
+                                               VPN_PROVIDER_STATE_CONNECT);
+
+                       vpn_provider_clear_address(provider, AF_INET);
+                       vpn_provider_clear_address(provider, AF_INET6);
+
+                       vpn_provider_change_address(provider);
+                       vpn_provider_set_state(provider,
+                                               VPN_PROVIDER_STATE_READY);
+                       break;
+               }
+
                index = vpn_provider_get_index(provider);
                vpn_provider_ref(provider);
                data->watch = vpn_rtnl_add_newlink_watch(index,
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index 5bc6093..f922730 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -2308,19 +2308,41 @@ int vpn_provider_set_ipaddress(struct vpn_provider 
*provider,
                break;
        }
 
-       DBG("provider %p ipconfig %p family %d", provider, ipconfig,
-                                                       ipaddress->family);
+       DBG("provider %p state %d ipconfig %p family %d", provider,
+               provider->state, ipconfig, ipaddress->family);
 
        if (!ipconfig)
                return -EINVAL;
 
        provider->family = ipaddress->family;
 
-       __vpn_ipconfig_set_local(ipconfig, ipaddress->local);
-       __vpn_ipconfig_set_peer(ipconfig, ipaddress->peer);
-       __vpn_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
-       __vpn_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
-       __vpn_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
+       if (provider->state == VPN_PROVIDER_STATE_CONNECT ||
+                       provider->state == VPN_PROVIDER_STATE_READY) {
+               struct connman_ipaddress *addr =
+                                       __vpn_ipconfig_get_address(ipconfig);
+
+               /*
+                * Remember the old address so that we can remove it in notify
+                * function in plugins/vpn.c if we ever restart
+                */
+               if (ipaddress->family == AF_INET6) {
+                       connman_ipaddress_free(provider->prev_ipv6_addr);
+                       provider->prev_ipv6_addr =
+                                               connman_ipaddress_copy(addr);
+               } else {
+                       connman_ipaddress_free(provider->prev_ipv4_addr);
+                       provider->prev_ipv4_addr =
+                                               connman_ipaddress_copy(addr);
+               }
+       }
+
+       if (ipaddress->local) {
+               __vpn_ipconfig_set_local(ipconfig, ipaddress->local);
+               __vpn_ipconfig_set_peer(ipconfig, ipaddress->peer);
+               __vpn_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
+               __vpn_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
+               __vpn_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
+       }
 
        return 0;
 }
-- 
1.8.3.1

_______________________________________________
connman mailing list
connman@connman.net
https://lists.connman.net/mailman/listinfo/connman

Reply via email to