Send connman mailing list submissions to
        connman@lists.01.org

To subscribe or unsubscribe via email, send a message with subject or
body 'help' to
        connman-requ...@lists.01.org

You can reach the person managing the list at
        connman-ow...@lists.01.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."

Today's Topics:

   1. [RFC 2/8] network: Support ipconfig.c changes for IPv6 force option
      (Jussi Laakkonen)
   2. [RFC 3/8] network: Prevent enabling IPv6 for network if internally 
disabled
      (Jussi Laakkonen)
   3. [RFC 4/8] service: Support IPv6 enable/disable for connected services
      (Jussi Laakkonen)
   4. [RFC 5/8] provider: Toggle IPv6 on the transport of IPv4 VPN connection
      (Jussi Laakkonen)


----------------------------------------------------------------------

Date: Fri, 26 Mar 2021 17:58:19 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [RFC 2/8] network: Support ipconfig.c changes for IPv6 force
        option
To: connman@lists.01.org
Message-ID: <20210326155825.3938-3-jussi.laakko...@jolla.com>

Add "false" to all functions using
__connman_ipconfig_{enable,disable}_ipv6() except with
__connman_network_enable_ipconfig(), in which the parameter is set by
the caller. This is passed to autoconf_ipv6_set() to get IPv6 properly
enabled again, when requested. Utilize the input force value with
FIXED, MANUAL, DHCP and AUTO ipconfig method types when enabling
ipconfig via network.c.

Use the force option "true" when clearing the IPv6 address in
set_disconnect(). Disabling does not need the forced option but when
re-enabling it is required in order to return the proper /proc values
for the interface in case IPv6 was disabled for IPv4 VPN.
---
 src/connman.h |  3 ++-
 src/network.c | 44 ++++++++++++++++++++++++++++----------------
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/src/connman.h b/src/connman.h
index 1ffce3e1..f775202c 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -616,7 +616,8 @@ int __connman_network_disconnect(struct connman_network 
*network);
 int __connman_network_clear_ipconfig(struct connman_network *network,
                                        struct connman_ipconfig *ipconfig);
 int __connman_network_enable_ipconfig(struct connman_network *network,
-                               struct connman_ipconfig *ipconfig);
+                               struct connman_ipconfig *ipconfig,
+                               bool force);
 
 const char *__connman_network_get_type(struct connman_network *network);
 const char *__connman_network_get_group(struct connman_network *network);
diff --git a/src/network.c b/src/network.c
index 256e3b5f..d23f54e5 100644
--- a/src/network.c
+++ b/src/network.c
@@ -296,7 +296,8 @@ static void acd_host_ipv4_lost(struct acd_host *acd, 
gpointer user_data)
                 */
                network = __connman_service_get_network(service);
                if (network)
-                       __connman_network_enable_ipconfig(network, 
ipconfig_ipv4);
+                       __connman_network_enable_ipconfig(network,
+                                                       ipconfig_ipv4, false);
        } else {
                /* Start IPv4LL ACD. */
                start_ipv4ll(network);
@@ -596,7 +597,8 @@ void connman_network_set_connected_dhcp_later(struct 
connman_network *network,
 }
 
 static int manual_ipv6_set(struct connman_network *network,
-                               struct connman_ipconfig *ipconfig_ipv6)
+                               struct connman_ipconfig *ipconfig_ipv6,
+                               bool force)
 {
        struct connman_service *service;
        int err;
@@ -610,7 +612,9 @@ static int manual_ipv6_set(struct connman_network *network,
        if (!__connman_ipconfig_get_local(ipconfig_ipv6))
                __connman_service_read_ip6config(service);
 
-       __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
+       err = __connman_ipconfig_enable_ipv6(ipconfig_ipv6, force);
+       if (err)
+               return err;
 
        err = __connman_ipconfig_address_add(ipconfig_ipv6);
        if (err < 0) {
@@ -688,7 +692,7 @@ err:
        return err;
 }
 
-static void autoconf_ipv6_set(struct connman_network *network);
+static void autoconf_ipv6_set(struct connman_network *network, bool force);
 static void dhcpv6_callback(struct connman_network *network,
                        enum __connman_dhcpv6_status status, gpointer data);
 
@@ -710,7 +714,7 @@ static void dhcpv6_renew_callback(struct connman_network 
*network,
                stop_dhcpv6(network);
 
                /* restart and do solicit again. */
-               autoconf_ipv6_set(network);
+               autoconf_ipv6_set(network, false);
                break;
        }
 }
@@ -736,7 +740,7 @@ static void dhcpv6_callback(struct connman_network *network,
 
        } else if (status == CONNMAN_DHCPV6_STATUS_RESTART) {
                stop_dhcpv6(network);
-               autoconf_ipv6_set(network);
+               autoconf_ipv6_set(network, false);
        } else
                stop_dhcpv6(network);
 }
@@ -868,7 +872,7 @@ int __connman_network_refresh_rs_ipv6(struct 
connman_network *network,
        return ret;
 }
 
-static void autoconf_ipv6_set(struct connman_network *network)
+static void autoconf_ipv6_set(struct connman_network *network, bool force)
 {
        struct connman_service *service;
        struct connman_ipconfig *ipconfig;
@@ -898,7 +902,8 @@ static void autoconf_ipv6_set(struct connman_network 
*network)
 
        __connman_ipconfig_enable(ipconfig);
 
-       __connman_ipconfig_enable_ipv6(ipconfig);
+       if (__connman_ipconfig_enable_ipv6(ipconfig, force))
+               return;
 
        __connman_ipconfig_address_remove(ipconfig);
 
@@ -932,8 +937,8 @@ static void set_connected(struct connman_network *network)
        DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
                ipconfig_ipv6);
 
-       __connman_network_enable_ipconfig(network, ipconfig_ipv4);
-       __connman_network_enable_ipconfig(network, ipconfig_ipv6);
+       __connman_network_enable_ipconfig(network, ipconfig_ipv4, false);
+       __connman_network_enable_ipconfig(network, ipconfig_ipv6, false);
 }
 
 static void set_disconnected(struct connman_network *network)
@@ -1036,8 +1041,14 @@ static void set_disconnected(struct connman_network 
*network)
                 * automagically.
                 */
                if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
-                       __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
-                       __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
+                       __connman_ipconfig_disable_ipv6(ipconfig_ipv6, false);
+                       /*
+                        * Use forced value when re-enabling IPv6 in order to
+                        * set the /proc values back to originals if the
+                        * network is being set disconnected while IPv6 is
+                        * disabled for a IPv4 VPN.
+                        */
+                       __connman_ipconfig_enable_ipv6(ipconfig_ipv6, true);
                }
        }
 
@@ -1898,7 +1909,7 @@ int __connman_network_clear_ipconfig(struct 
connman_network *network,
 }
 
 int __connman_network_enable_ipconfig(struct connman_network *network,
-                               struct connman_ipconfig *ipconfig)
+                               struct connman_ipconfig *ipconfig, bool force)
 {
        int r = 0;
        enum connman_ipconfig_type type;
@@ -1926,19 +1937,20 @@ int __connman_network_enable_ipconfig(struct 
connman_network *network,
                        break;
 
                case CONNMAN_IPCONFIG_METHOD_OFF:
-                       __connman_ipconfig_disable_ipv6(ipconfig);
+                       __connman_ipconfig_disable_ipv6(ipconfig, force);
                        break;
 
                case CONNMAN_IPCONFIG_METHOD_AUTO:
-                       autoconf_ipv6_set(network);
+                       autoconf_ipv6_set(network, force);
                        break;
 
                case CONNMAN_IPCONFIG_METHOD_FIXED:
                case CONNMAN_IPCONFIG_METHOD_MANUAL:
-                       r = manual_ipv6_set(network, ipconfig);
+                       r = manual_ipv6_set(network, ipconfig, force);
                        break;
 
                case CONNMAN_IPCONFIG_METHOD_DHCP:
+                       __connman_ipconfig_enable_ipv6(ipconfig, force);
                        r = -ENOSYS;
                        break;
                }
-- 
2.20.1

------------------------------

Date: Fri, 26 Mar 2021 17:58:20 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [RFC 3/8] network: Prevent enabling IPv6 for network if
        internally disabled
To: connman@lists.01.org
Message-ID: <20210326155825.3938-4-jussi.laakko...@jolla.com>

If a new connection comes up/is manually connected when IPv6 is
internally disabled for a IPv4 VPN the IPv6 configuration for the
network must be prevented. If the different IPv6 method functions do
this then an error is received from ipconfig.c which will propagate to
disabling of the new connection completely as network error is
triggered. This way IPv6 is silently ignored and forcefully set as
disabled to be re-enabled when VPN is disconnected.
---
 src/network.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/network.c b/src/network.c
index d23f54e5..53225235 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1926,6 +1926,23 @@ int __connman_network_enable_ipconfig(struct 
connman_network *network,
                return -ENOSYS;
 
        case CONNMAN_IPCONFIG_TYPE_IPV6:
+               /*
+                *If enabling IPv6 for new network while IPv6 support is
+                * disabled enforce the ipconfig to be completely disabled to
+                * disable autoconf and to avoid IPv6 address being set.
+                */
+               if (!__connman_ipconfig_get_ipv6_support()) {
+                       DBG("ipv6 not enabled, force disable %p", ipconfig);
+
+                       __connman_ipconfig_ipv6_method_save(ipconfig);
+                       __connman_ipconfig_set_method(ipconfig,
+                                               CONNMAN_IPCONFIG_METHOD_OFF);
+
+                       __connman_ipconfig_disable_ipv6(ipconfig, true);
+
+                       return 0;
+               }
+
                set_configuration(network, type);
 
                method = __connman_ipconfig_get_method(ipconfig);
-- 
2.20.1

------------------------------

Date: Fri, 26 Mar 2021 17:58:21 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [RFC 4/8] service: Support IPv6 enable/disable for connected
        services
To: connman@lists.01.org
Message-ID: <20210326155825.3938-5-jussi.laakko...@jolla.com>

Implement support for enabling/disabling IPv6 for every connected
service exluding the VPN and including the VPN transport. This is used
when an IPv4 VPN is connected to avoid leaking of data to IPv6 network
by disabling IPv6 for all services when connected and when disconnecting
the VPN re-enable IPv6.

When disabling the old IPv6 method is recorded, address is cleared, IPv6
network is disconnected, then turned to idle and notified. When enabling
IPv6 method is restored and simply enabling the ipconfig is required in
order to get the IPv6 connectivity to be resumed. In case the transport
has been disconnected prior to VPN disconnect it is imperative to do the
changes only to ipconfig to avoid changing the state of the transport.

Enable/disable IPv6 on VPNs transport when the split routing value is
changed. This is important in both cases when a connected IPv4 VPN has
the value changed as with split routing -> non-split routing IPv6 should
be disabled as well as non-split-routing -> split routed IPv6 should be
re-enabled.
---
 src/connman.h |   2 +
 src/service.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 151 insertions(+), 9 deletions(-)

diff --git a/src/connman.h b/src/connman.h
index f775202c..9fb989c8 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -695,6 +695,8 @@ int __connman_service_compare(const struct connman_service 
*a,
 
 struct connman_service *__connman_service_lookup_from_index(int index);
 struct connman_service *__connman_service_create_from_network(struct 
connman_network *network);
+void __connman_service_set_ipv6_for_connected(struct connman_service *vpn,
+                               struct connman_service *transport, bool enable);
 struct connman_service *__connman_service_create_from_provider(struct 
connman_provider *provider);
 bool __connman_service_index_is_default(int index);
 void __connman_service_update_from_network(struct connman_network *network);
diff --git a/src/service.c b/src/service.c
index dfb5a93c..cc0b20ef 100644
--- a/src/service.c
+++ b/src/service.c
@@ -387,12 +387,18 @@ void __connman_service_split_routing_changed(struct 
connman_service *service)
                                        service->identifier);
 }
 
+static bool is_connected(enum connman_service_state state);
+
 void __connman_service_set_split_routing(struct connman_service *service,
                                                                bool value)
 {
+       bool change;
+
        if (service->type != CONNMAN_SERVICE_TYPE_VPN)
                return;
 
+       change = service->do_split_routing != value;
+
        service->do_split_routing = value;
 
        if (service->do_split_routing)
@@ -400,6 +406,20 @@ void __connman_service_set_split_routing(struct 
connman_service *service,
        else
                service->order = 10;
 
+       /*
+        * Change IPv6 on the VPN transport when split routing value changes
+        * on a connected IPv4 VPN.
+        */
+       if (connman_provider_get_family(service->provider) == AF_INET &&
+                               change && is_connected(service->state)) {
+               if (__connman_provider_set_ipv6_for_connected(
+                                                       service->provider,
+                                                       value))
+                       DBG("cannot %s IPv6 for VPN service %p provider %p",
+                                               value ? "enable" : "disable",
+                                               service, service->provider);
+       }
+
        /*
         * In order to make sure the value is propagated also when loading the
         * VPN service signal the value regardless of the value change.
@@ -3874,11 +3894,15 @@ static DBusMessage *set_property(DBusConnection *conn,
                if (err < 0) {
                        if (is_connected(state) || is_connecting(state)) {
                                if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
-                                       
__connman_network_enable_ipconfig(service->network,
-                                                       service->ipconfig_ipv4);
+                                       __connman_network_enable_ipconfig(
+                                                       service->network,
+                                                       service->ipconfig_ipv4,
+                                                       false);
                                else
-                                       
__connman_network_enable_ipconfig(service->network,
-                                                       service->ipconfig_ipv6);
+                                       __connman_network_enable_ipconfig(
+                                                       service->network,
+                                                       service->ipconfig_ipv6,
+                                                       false);
                        }
 
                        return __connman_error_failed(msg, -err);
@@ -3892,11 +3916,15 @@ static DBusMessage *set_property(DBusConnection *conn,
                if (is_connecting(service->state) ||
                                is_connected(service->state)) {
                        if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
-                               
__connman_network_enable_ipconfig(service->network,
-                                                               
service->ipconfig_ipv4);
+                               __connman_network_enable_ipconfig(
+                                                       service->network,
+                                                       service->ipconfig_ipv4,
+                                                       false);
                        else
-                               
__connman_network_enable_ipconfig(service->network,
-                                                               
service->ipconfig_ipv6);
+                               __connman_network_enable_ipconfig(
+                                                       service->network,
+                                                       service->ipconfig_ipv6,
+                                                       false);
                }
 
                service_save(service);
@@ -6017,7 +6045,7 @@ static int service_indicate_state(struct connman_service 
*service)
                method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
                if (method == CONNMAN_IPCONFIG_METHOD_OFF)
                        __connman_ipconfig_disable_ipv6(
-                                               service->ipconfig_ipv6);
+                                               service->ipconfig_ipv6, false);
 
                if (connman_setting_get_bool("SingleConnectedTechnology"))
                        single_connected_tech(service);
@@ -7160,6 +7188,118 @@ struct connman_service 
*__connman_service_lookup_from_index(int index)
        return NULL;
 }
 
+struct set_ipv6_data {
+       struct connman_service *vpn;
+       struct connman_service *transport;
+       bool enable;
+};
+
+static void set_ipv6_for_service(gpointer value, gpointer user_data)
+{
+       struct connman_service *service = value;
+       struct connman_ipconfig *ipconfig;
+       struct connman_network *network;
+       struct set_ipv6_data *data = user_data;
+       int err;
+
+       /*
+        * Ignore the vpn and not connected unless it is the transport. It is
+        * imperative to set the IPv6 parameters on the transport even though
+        * it is being disconnected. This ensures that the interface it is/was
+        * using is set to the previous state.
+        */
+       if ((!is_connected(service->state) || service == data->vpn) &&
+                                               service != data->transport)
+               return;
+
+       DBG("%s service %p/%s", data->enable ? "enable" : "disable", service,
+                                                       service->identifier);
+
+       network = service->network;
+       if (!network)
+               return;
+
+       ipconfig = service->ipconfig_ipv6;
+       if (!ipconfig)
+               return;
+
+       if (data->enable == __connman_ipconfig_ipv6_is_enabled(ipconfig)) {
+               DBG("Ignore service, IPv6 already %s",
+                                       data->enable ? "enabled" : "disabled");
+               return;
+       }
+
+       if (data->enable) {
+               /*
+                * Restore old method, force_disabled gets unset when enabling
+                * as forced setting.
+                */
+               __connman_ipconfig_ipv6_method_restore(ipconfig);
+
+               /*
+                * When changing to use another service the current service
+                * used as transport is disconnected first and in that case
+                * simply enable IPv6 via ipconfig instead of network to avoid
+                * state changes.
+                */
+               if (service == data->transport &&
+                                               !is_connected(service->state))
+                       err = __connman_ipconfig_enable_ipv6(ipconfig, true);
+               else
+                       err = __connman_network_enable_ipconfig(network,
+                                                       ipconfig, true);
+
+               if (err)
+                       connman_warn("cannot re-enable IPv6 on %s",
+                                               service->identifier);
+       } else {
+               /* Save the IPv6 method for enabling and clear network conf */
+               __connman_ipconfig_ipv6_method_save(ipconfig);
+               __connman_network_clear_ipconfig(network, ipconfig);
+               __connman_ipconfig_gateway_remove(ipconfig);
+
+               /* Disconnect and clear address */
+               __connman_service_ipconfig_indicate_state(service,
+                                       CONNMAN_SERVICE_STATE_DISCONNECT,
+                                       CONNMAN_IPCONFIG_TYPE_IPV6);
+               __connman_ipconfig_address_unset(ipconfig);
+
+               /*
+                * Disables IPv6 on ipconfig and sets the force_disabled
+                * as true.
+                */
+               __connman_ipconfig_set_method(ipconfig,
+                                               CONNMAN_IPCONFIG_METHOD_OFF);
+               err = __connman_network_enable_ipconfig(network, ipconfig,
+                                                                       true);
+               if (err)
+                       connman_warn("cannot disable IPv6 on %s",
+                                                       service->identifier);
+
+               __connman_service_ipconfig_indicate_state(service,
+                                               CONNMAN_SERVICE_STATE_IDLE,
+                                               CONNMAN_IPCONFIG_TYPE_IPV6);
+       }
+
+       ipv6_configuration_changed(service);
+       __connman_notifier_ipconfig_changed(service, ipconfig);
+}
+
+void __connman_service_set_ipv6_for_connected(struct connman_service *vpn,
+                               struct connman_service *transport, bool enable)
+{
+       struct set_ipv6_data data = {
+               .vpn = vpn,
+               .transport = transport,
+               .enable = enable
+       };
+
+       DBG("%s vpn %p transport %p", enable ? "enable" : "disable", vpn,
+                                                               transport);
+
+       g_list_foreach(service_list, set_ipv6_for_service, &data);
+}
+
 const char *connman_service_get_identifier(struct connman_service *service)
 {
        return service ? service->identifier : NULL;
-- 
2.20.1

------------------------------

Date: Fri, 26 Mar 2021 17:58:22 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [RFC 5/8] provider: Toggle IPv6 on the transport of IPv4 VPN
        connection
To: connman@lists.01.org
Message-ID: <20210326155825.3938-6-jussi.laakko...@jolla.com>

Add support to disable/enable IPv6 on the transport of the VPN that uses
IPv4. This change eliminates the data and DNS leak to IPv6 when
dual-stack transport is used on a IPv4 only VPN. Otherwise with an AAAA
record for a requested hostname the traffic can bypass the VPN to
transport's IPv6 network if the DNS server of the VPN serves both A
and AAAA requests.

If multiple connection technologies (SingleConnectedTechnology omitted
or false) are in use IPv6 support is changed internally as well. The
value of SingleConnectedTechnology does not change run-time so there is
no possibility for inconsistent state. When re-enabling IPv6 enable the
internal IPv6 suppor prior to resuming IPv6 functionality on service
basis. When disabling IPv6 do the internal disabling after the services
are handled. This is due to the changes that were required for network.c
to get new connections enabled but IPv6 disabled if IPv6 is internally
disabled.

Disable IPv6 when state changes to READY (also ONLINE but that is never
used with VPNs) for IPv4 provider. Allow to change IPv6 only for VPNs
that are connected (READY).

When provider state changes to DISCONNECT or FAILURE re-enable IPv6 the
transport using the recorded method. Prevent running the function as a
loop within loop. This might happen when current transport service is
disconnected that in turn causes the VPN to be disconnected as well.
Then while looping through the services another disconnect on the
transport will get provider_indicate_state() called again.
---
 src/connman.h  |   3 ++
 src/provider.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/src/connman.h b/src/connman.h
index 9fb989c8..9f859f19 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -677,6 +677,9 @@ int __connman_provider_indicate_error(struct 
connman_provider *provider,
 int __connman_provider_connect(struct connman_provider *provider,
                                        const char *dbus_sender);
 int __connman_provider_remove_by_path(const char *path);
+int __connman_provider_set_ipv6_for_connected(
+                                       struct connman_provider *provider,
+                                       bool enable);
 void __connman_provider_cleanup(void);
 int __connman_provider_init(void);
 
diff --git a/src/provider.c b/src/provider.c
index 1eae4951..250865f0 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -121,11 +121,129 @@ void connman_provider_unref_debug(struct 
connman_provider *provider,
        provider_destruct(provider);
 }
 
+static bool ipv6_change_running = false;
+
+int __connman_provider_set_ipv6_for_connected(
+                               struct connman_provider *provider, bool enable)
+{
+       struct connman_service *service;
+       struct connman_service *transport;
+       struct connman_ipconfig *ipconfig;
+       enum connman_service_state state;
+       const char *transport_ident;
+       bool single_connected_tech;
+
+       if (ipv6_change_running)
+               return -EALREADY;
+
+       if (!provider)
+               return -EINVAL;
+
+       DBG("provider %p %s", provider, enable ? "enable" : "disable");
+
+       service = provider->vpn_service;
+       if (!service)
+               return -EINVAL;
+
+       /*
+        * Allow only when the VPN service is in ready state, service state
+        * is changed to ready before provider when connecting and changed
+        * away from ready after provider state is changed.
+        */
+       state = connman_service_get_state(service);
+       if (state != CONNMAN_SERVICE_STATE_READY)
+               return 0;
+
+       /*
+        * If a VPN changes from non-split routed to split routed then IPv6 on
+        * the transport must be re-enabled.
+        */
+       if (__connman_service_is_split_routing(service) && !enable)
+               return 0;
+
+       ipconfig = __connman_service_get_ip6config(service);
+       if (__connman_ipconfig_ipv6_is_enabled(ipconfig))
+               return 0;
+
+       single_connected_tech =
+                       connman_setting_get_bool("SingleConnectedTechnology");
+
+       /* If re-enabling IPv6 set the internal status prior to enabling IPv6
+        * for connected servises to allow the ipconfig method to be changed
+        * via __connman_network_enable_ipconfig().
+        */
+       if (enable && !single_connected_tech)
+               __connman_ipconfig_set_ipv6_support(enable);
+
+       transport_ident = __connman_provider_get_transport_ident(provider);
+       transport = connman_service_lookup_from_identifier(transport_ident);
+
+       /* In case a sevice of same type that the current transport is changed
+        * to use another, e.g., WiFi AP, then the service is first
+        * disconnected which in turn calls provider_indicate_state() when
+        * provider is being disconnected and this function gets called. In
+        * such case another call to provider_indicate_state() can be made
+        * while traversing through the services list with
+        * __connman_service_set_ipv6_for_connected() to disconnect this
+        * provider. Therefore, using this boolean can prevent a loop within
+        * loop from being executed.
+        */
+       ipv6_change_running = true;
+       
+       /* Set IPv6 for connected, excluding VPN and include transport. */
+       __connman_service_set_ipv6_for_connected(service, transport, enable);
+
+       /*
+        * Disable internal IPv6 use after disabling IPv6 for the connected
+        * services because __connman_network_enable_ipconfig() is used for
+        * force disabling.
+        */
+       if (!enable && !single_connected_tech)
+               __connman_ipconfig_set_ipv6_support(enable);
+
+       ipv6_change_running = false;
+
+       return 0;
+}
+
 static int provider_indicate_state(struct connman_provider *provider,
                                        enum connman_service_state state)
 {
+       int err;
+
        DBG("state %d", state);
 
+       switch (state) {
+       case CONNMAN_SERVICE_STATE_UNKNOWN:
+       case CONNMAN_SERVICE_STATE_IDLE:
+       case CONNMAN_SERVICE_STATE_ASSOCIATION:
+       case CONNMAN_SERVICE_STATE_CONFIGURATION:
+               break;
+       case CONNMAN_SERVICE_STATE_READY:
+       case CONNMAN_SERVICE_STATE_ONLINE:
+               if (provider->family != AF_INET)
+                       break;
+
+               err = __connman_provider_set_ipv6_for_connected(provider,
+                                                                       false);
+               if (err && err != -EALREADY)
+                       DBG("cannot disable IPv6 on provider %p transport",
+                                                               provider);
+               break;
+       case CONNMAN_SERVICE_STATE_DISCONNECT:
+       case CONNMAN_SERVICE_STATE_FAILURE:
+               if (provider->family != AF_INET)
+                       break;
+
+               err = __connman_provider_set_ipv6_for_connected(provider,
+                                                                       true);
+               if (err && err != -EALREADY)
+                       DBG("cannot enable IPv6 on provider %p transport",
+                                                               provider);
+
+               break;
+       }
+
        __connman_service_ipconfig_indicate_state(provider->vpn_service, state,
                                        CONNMAN_IPCONFIG_TYPE_IPV4);
 
-- 
2.20.1

------------------------------

Subject: Digest Footer

_______________________________________________
connman mailing list -- connman@lists.01.org
To unsubscribe send an email to connman-le...@lists.01.org


------------------------------

End of connman Digest, Vol 65, Issue 8
**************************************

Reply via email to