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. [PATCH 06/11] network: Adopt to new IPv6 disabled functionality of 
ipconfig.c
      (Jussi Laakkonen)
   2. [PATCH 07/11] service: Support IPv6 enable/disable for connected services
      (Jussi Laakkonen)
   3. [PATCH 08/11] provider: Toggle IPv6 on the transport of IPv4 VPN 
connection
      (Jussi Laakkonen)
   4. [PATCH 09/11] service: Change IPv6 support if split routing value changes 
on IPv4 VPN
      (Jussi Laakkonen)
   5. [PATCH 10/11] doc: Add note to SingleConnectedTech on IPv4 VPN data leak 
prevention
      (Jussi Laakkonen)
   6. [PATCH 11/11] TODO: Add task about IPv6 only connection with IPv4 VPN
      (Jussi Laakkonen)


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

Date: Thu,  1 Apr 2021 17:46:13 +0300
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 06/11] network: Adopt to new IPv6 disabled
        functionality of ipconfig.c
To: connman@lists.01.org
Message-ID: <20210401144618.12936-7-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.

Disable force disabled in IPv6 ipconfig when clearing the IPv6 address
in set_disconnect(). This is required when re-enabling IPv6 for kernel
to clear the values in order to return the proper /proc values for the
interface in case IPv6 was disabled for IPv4 VPN. Also restore the
original IPv6 method before setting disconnected to make kernel know
about the changes as well. Otherwise IPv6 on some occasions is not
enabled on the interface when, e.g., changing to another service of same
type technology.

Adapt to ipconfig.c changes by reporting back potential errors.
---
 src/network.c | 41 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/src/network.c b/src/network.c
index 256e3b5f..388e9bbe 100644
--- a/src/network.c
+++ b/src/network.c
@@ -610,7 +610,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);
+       if (err)
+               return err;
 
        err = __connman_ipconfig_address_add(ipconfig_ipv6);
        if (err < 0) {
@@ -898,7 +900,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))
+               return;
 
        __connman_ipconfig_address_remove(ipconfig);
 
@@ -952,6 +955,21 @@ static void set_disconnected(struct connman_network 
*network)
                ipconfig_ipv6);
 
        ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
+
+       /*
+        * If disconnecting a force disabled IPv6 restore the old method and
+        * remove force disabled to allow enabling of IPv6 for kernel to
+        * cleanup the addresses. This is crucial when changing to another same
+        * type service, e.g., WiFi in order to properly get IPv6 re-enabled
+        * via kernel.
+        */
+       if (ipconfig_ipv6 && __connman_ipconfig_ipv6_get_force_disabled(
+                                                       ipconfig_ipv6)) {
+               __connman_ipconfig_ipv6_set_force_disabled(ipconfig_ipv6,
+                                                                       false);
+               __connman_ipconfig_ipv6_method_restore(ipconfig_ipv6);
+       }
+
        ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
 
        DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
@@ -1915,6 +1933,25 @@ 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
+                * 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);
+                       __connman_ipconfig_ipv6_set_force_disabled(ipconfig,
+                                                                       true);
+
+                       return 0;
+               }
+
                set_configuration(network, type);
 
                method = __connman_ipconfig_get_method(ipconfig);
-- 
2.20.1

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

Date: Thu,  1 Apr 2021 17:46:14 +0300
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 07/11] service: Support IPv6 enable/disable for
        connected services
To: connman@lists.01.org
Message-ID: <20210401144618.12936-8-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.
---
 src/connman.h |   2 +
 src/service.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/src/connman.h b/src/connman.h
index 0a8adbd3..598e2970 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -701,6 +701,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 7dfa89f2..b164de3a 100644
--- a/src/service.c
+++ b/src/service.c
@@ -7233,6 +7233,120 @@ 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 the original method before enabling. */
+               __connman_ipconfig_ipv6_method_restore(ipconfig);
+
+               /* To allow enabling remove force disabled. */
+               __connman_ipconfig_ipv6_set_force_disabled(ipconfig, false);
+
+               /*
+                * 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);
+               else
+                       err = __connman_network_enable_ipconfig(network,
+                                                               ipconfig);
+
+               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_remove(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);
+               if (err)
+                       connman_warn("cannot disable IPv6 on %s",
+                                                       service->identifier);
+
+               /* Set force disabled on after disabling. */
+               __connman_ipconfig_ipv6_set_force_disabled(ipconfig, true);
+
+               __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: Thu,  1 Apr 2021 17:46:15 +0300
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 08/11] provider: Toggle IPv6 on the transport of IPv4
        VPN connection
To: connman@lists.01.org
Message-ID: <20210401144618.12936-9-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 do the change 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 | 117 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+)

diff --git a/src/connman.h b/src/connman.h
index 598e2970..58f49b5d 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -683,6 +683,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 51bbfdf4..ecd4a342 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -121,11 +121,128 @@ 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 IPv6 ipconfig enabled check to
+        * return correct value.
+        */
+       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 to allow IPv6 enabled check to work.
+        */
+       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

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

Date: Thu,  1 Apr 2021 17:46:16 +0300
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 09/11] service: Change IPv6 support if split routing
        value changes on IPv4 VPN
To: connman@lists.01.org
Message-ID: <20210401144618.12936-10-jussi.laakko...@jolla.com>

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/service.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/src/service.c b/src/service.c
index b164de3a..07032e8f 100644
--- a/src/service.c
+++ b/src/service.c
@@ -388,12 +388,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)
@@ -401,6 +407,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.
-- 
2.20.1

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

Date: Thu,  1 Apr 2021 17:46:17 +0300
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 10/11] doc: Add note to SingleConnectedTech on IPv4
        VPN data leak prevention
To: connman@lists.01.org
Message-ID: <20210401144618.12936-11-jussi.laakko...@jolla.com>

Describe the behavior on having IPv4 VPN connected if IPv6 only
connection is attempted to be established with SingleConnectedTech
disabled.
---
 doc/connman.conf.5.in | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/connman.conf.5.in b/doc/connman.conf.5.in
index 2e06b3ef..52e75962 100644
--- a/doc/connman.conf.5.in
+++ b/doc/connman.conf.5.in
@@ -130,6 +130,10 @@ the only one that will be kept connected. A service 
connected by the
 user will be used until going out of network coverage. With this
 setting enabled applications will notice more network breaks than
 normal. Default value is false.
+NOTE that when this setting is disabled and IPv4 VPN is connected an
+IPv6 only connection cannot be connected until VPN is disconnected.
+This is a side-effect of preventing data leak to IPv6 when using IPv4
+VPN connections.
 .TP
 .BI TetheringTechnologies= technology\fR[,...]
 List of technologies that are allowed to enable tethering separated by ",".
-- 
2.20.1

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

Date: Thu,  1 Apr 2021 17:46:18 +0300
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 11/11] TODO: Add task about IPv6 only connection with
        IPv4 VPN
To: connman@lists.01.org
Message-ID: <20210401144618.12936-12-jussi.laakko...@jolla.com>

---
 TODO | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/TODO b/TODO
index c10b8ce1..8d1ff2b9 100644
--- a/TODO
+++ b/TODO
@@ -229,6 +229,17 @@ VPN
    server certificate as it is done now, otherwise indicate error to
    libopenconnect.
 
+- Figure out way to allow IPv6 service to connect while IPv4 VPN is connected
+
+   Priority: Low
+   Complexity: C?
+
+   Consider adding a feature to allow IPv6 only connection to connect even when
+   IPv4 VPN is connected and IPv6 is internally disabled to avoid leaking of 
data
+   to IPv6 network. This is a tricky issue, would the VPN be required to 
disconnect
+   in such case or just to leave the IPv6 only connection to some pending state
+   until VPN disconnect happens.
+
 Tools
 =====
 
-- 
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 66, Issue 1
**************************************

Reply via email to