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] dnsproxy: Enable DNS servers on connected VPN if split routing changes (Jussi Laakkonen) 2. Re: [PATCH] service: Allow only user connection after WiFi failure (Jussi Laakkonen) 3. [RFC 0/8] Prevent IPv4 VPN data/DNS leak to IPv6 network(s) (Jussi Laakkonen) 4. [RFC 1/8] ipconfig: Add disabling of IPv6, support method restore and refactor (Jussi Laakkonen) ---------------------------------------------------------------------- Date: Fri, 26 Mar 2021 14:45:53 +0200 From: Jussi Laakkonen <jussi.laakko...@jolla.com> Subject: [PATCH] dnsproxy: Enable DNS servers on connected VPN if split routing changes To: connman@lists.01.org Message-ID: <20210326124553.5851-1-jussi.laakko...@jolla.com> If split routing is enabled on a connected VPN the DNS servers of the VPN should be enabled as well when the default service is switched to be the transport service. --- src/dnsproxy.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 4f5c897f..de52df5a 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -2885,6 +2885,7 @@ static void dnsproxy_default_changed(struct connman_service *service) bool server_enabled = false; GSList *list; int index; + int vpn_index; DBG("service %p", service); @@ -2901,6 +2902,13 @@ static void dnsproxy_default_changed(struct connman_service *service) if (index < 0) return; + /* + * In case non-split-routed VPN is set as split routed the DNS servers + * the VPN must be enabled as well, when the transport becomes the + * default service. + */ + vpn_index = __connman_connection_get_vpn_index(index); + for (list = server_list; list; list = list->next) { struct server_data *data = list->data; @@ -2908,6 +2916,9 @@ static void dnsproxy_default_changed(struct connman_service *service) DBG("Enabling DNS server %s", data->server); data->enabled = true; server_enabled = true; + } else if (data->index == vpn_index) { + DBG("Enabling DNS server of VPN %s", data->server); + data->enabled = true; } else { DBG("Disabling DNS server %s", data->server); data->enabled = false; -- 2.20.1 ------------------------------ Date: Fri, 26 Mar 2021 17:25:15 +0200 From: Jussi Laakkonen <jussi.laakko...@jolla.com> Subject: Re: [PATCH] service: Allow only user connection after WiFi failure To: "VAUTRIN Emmanuel (Canal Plus Prestataire)" <emmanuel.vaut...@cpexterne.org>, "connman@lists.01.org" <connman@lists.01.org> Message-ID: <b6bbb4f0-ab67-0e71-e43e-887de3e84...@jolla.com> Content-Type: text/plain; charset=utf-8; format=flowed Hi Emmanuel, On 3/11/21 3:06 PM, VAUTRIN Emmanuel (Canal Plus Prestataire) wrote: > The failure state may not always result from a bad connection. > For security matter, as a password renewal, the AP may disconnect the > station, and finally completely block it, after several inappropriate > retries, due to auto connection with former password. > --- > src/service.c | 14 ++++++++++---- > 1 file changed, 10 insertions(+), 4 deletions(-) > > diff --git a/src/service.c b/src/service.c > index a24dea729545..cd939320d3d5 100644 > --- a/src/service.c > +++ b/src/service.c > @@ -3447,16 +3447,22 @@ static void do_auto_connect(struct connman_service > *service, > reason == CONNMAN_SERVICE_CONNECT_REASON_NONE)) > return; > > + /* > + * Only user interaction should get VPN or WIFI connected in failure > + * state. > + */ > + if (service->state == CONNMAN_SERVICE_STATE_FAILURE && > + reason != CONNMAN_SERVICE_CONNECT_REASON_USER && > + (service->type == CONNMAN_SERVICE_TYPE_VPN || > + service->type == CONNMAN_SERVICE_TYPE_WIFI)) Could this be treated in some other manner as I suspect (I haven't tested this at all yet) that in mobile environment when AP is shut down, lost or it simply crashes and does not get up instantly (put down for maintenance) the service may end up in failure state? In that case user interaction would not be required for re-connecting and autoconnect should handle that case. But I understand your point here that repeatedly re-connecting has its downsides as well. We have our own implementation of the WiFi plugin and I haven't tried with the plugin upstream has so this is just a guess/concern from my part. So, if the WiFi plugin can in the cases I described result in failure state this may need some re-thinking. If not, please ignore this :) > + return; > + > /* > * Run service auto connect for other than VPN services. Afterwards > * start also VPN auto connect process. > */ > if (service->type != CONNMAN_SERVICE_TYPE_VPN) > __connman_service_auto_connect(reason); > - /* Only user interaction should get VPN connected in failure state. */ > - else if (service->state == CONNMAN_SERVICE_STATE_FAILURE && > - reason != CONNMAN_SERVICE_CONNECT_REASON_USER) > - return; > > vpn_auto_connect(); > } > Sincerely, Jussi Laakkonen ------------------------------ Date: Fri, 26 Mar 2021 17:58:17 +0200 From: Jussi Laakkonen <jussi.laakko...@jolla.com> Subject: [RFC 0/8] Prevent IPv4 VPN data/DNS leak to IPv6 network(s) To: connman@lists.01.org Message-ID: <20210326155825.3938-1-jussi.laakko...@jolla.com> This change is quite big, touching many places around the codebase and may have still some quirks to be polished out and therefore this is sent as an RFC first. The core idea of this is to prevent leaking of any data to an IPv6 network when an IPv4 VPN is used with dual-stack transport or when there are other connected IPv6 cabable technologies. Leak can happen when the DNS server of the VPN responds also to AAAA requests providing an IPv6 address as well. In that case IPv6 of the transport/other connected service will be used and traffic bypasses VPN. Prevention of data leak is achieved by disabling IPv6 on adapter basis with disable_ipv6 and autoconf values. It was not seen reasonable to disable IPv6 on system basis as there may be other interfaces that are not managed by ConnMan (blacklisted) which may require IPv6 to function properly. Therefore, this simply does disable IPv6 on all connected services when the IPv4 VPN is connected with the help of changes done to ipconfig.c. Setting the internal value to block IPv6 use within ConnMan is utilized only when there can be multiple connected technologies as otherwise the transport will get replaced and VPN is re-connected using the new transport. If multiple connected technologies is enabled and a new service connects then in this case it cannot first establish an IPv6 connection at all but if the particular service then ranks over the current service the VPN will be disconnected, IPv6 is re-enabled and the new service starts to establish an IPv6 connection. Otherwise the new service remains with IPv4 connectivity only - but if it is IPv6 only the service cannot connect and this is expected (might it be good to have this feature as a configurable option?). To be future-proof it may be better to have the new services to have their IPv6 network not enabled but forcefully disabled in case at the time of connection an IPv4 VPN is connected. Not only due to the fact that an IPv6 address is not attempted to be retrieved with the current approach for a newly connected network. Alternative would be to call __connman_provider_set_ipv6_for_connected() in case the default service is an IPv4 VPN to get the service list traversed. But in that case IPv6 connectivity may have been established and there might be a small timeframe for leaking traffic. It was also considered and prototyped to do this with DNS filtering but that did prove to be a bit problematic, hence the added delays in some cases to DNS requests and respective responses. Also disabling only the routes was considered but since it depends on the IPv6 network type and autoconfiguration of the interface it seemed to be safer and more consistent to do the change like this. But being a RFC any opinnion and comment is welcome. We have done some testing and in those this seems to work well. One thing to consider is whether to always set the autoconf value for an IPv6 enabled network interface or not, or to save it along other IPv6 values to be able to restore the previous value in case ConnMan crashes when the VPN is connected and IPv6 is disabled. Jussi Laakkonen (8): ipconfig: Add disabling of IPv6, support method restore and refactor network: Support ipconfig.c changes for IPv6 force option network: Prevent enabling IPv6 for network if internally disabled service: Support IPv6 enable/disable for connected services provider: Toggle IPv6 on the transport of IPv4 VPN connection vpn: Return transport ident with get_property() provider: Add function to get transport ident from VPN service: Sort VPNs using the transport service if connected plugins/vpn.c | 2 + src/connman.h | 20 +++- src/ipconfig.c | 290 +++++++++++++++++++++++++++++++++---------------- src/network.c | 61 ++++++++--- src/provider.c | 130 ++++++++++++++++++++++ src/service.c | 203 ++++++++++++++++++++++++++++++++-- 6 files changed, 583 insertions(+), 123 deletions(-) -- 2.20.1 ------------------------------ Date: Fri, 26 Mar 2021 17:58:18 +0200 From: Jussi Laakkonen <jussi.laakko...@jolla.com> Subject: [RFC 1/8] ipconfig: Add disabling of IPv6, support method restore and refactor To: connman@lists.01.org Message-ID: <20210326155825.3938-2-jussi.laakko...@jolla.com> Support complete disabling of IPv6 on both system and interface levels. Disabling of IPv6 completely albeit temporarily is required when there can be multiple connected technologies and a VPN is connected over IPv4 using an dual-stack transport and/or there is another technology with dual-stack or only IPv6 in use. This approach effectively ensures that no data from an IPv4 VPN leaks to any other interface. A DNS server returning replies to AAAA requests may return an IPv6 address, which could be then used over IPv6 routing on another technolology that is not acting as the transport of the VPN. Add getter and setter for the internal IPv6 status. When enabling check the status with connman_inet_is_ipv6_supported(). It is not the intention to disable IPv6 system-wide since there may be interfaces that should not be managed by ConnMan and are handled for other OS needs where IPv6 is required, e.g., VoLTE may be one of them. Add a "ipv6_force_disabled" toggle to indicate that the particular device tied to ipconfig should not have IPv6 enabled. This toggle is to be used in scenarios where IPv6 should be prevented from reinstating unless forcefully enabled. The __connman_ipconfig_{enable,disable}_ipv6() now have additional boolean to control this behavior, and the enabling function returns either -EINVAL or -EOPNOTSUPP for errors and 0 when success. When checking IPv6 enabled state return false if ipv6_force_disabled is set as that is the real status of IPv6. The /proc disable_ipv6 can change when kernel processes ICMPv6 (RA/RS) packets and brings the IPv6 interface up so using only the disable_ipv6 value is not consistent enough in case when IPv6 has been forcefully disabled. This change will prevent from changing the IPv6 status until it has it has been forcefully enabled. The most prominent use case for this is to prevent data as well as DNS leak to IPv6 when IPv4 only VPN is connected over a transport supporting both IPv4 and IPv6 connectivity. In addition to changing disable_ipv6 value also the autoconf option is managed. This is done in order to control the address setup for the interface. It is worthy to note that disable_ipv6 may be temporarily set to 0 by the kernel. This can happen when LL address is temporarily set as a typical behavior of IPv6 on some configurations to handle ICMPv6. After a while the value of disable_ipv6 as well as LL address are reset/removed by kernel. Also refactor getting and setting the proc conf values, have read and write in their own respective general functions. If write/read is issued without interface name (NULL) then "all" section is used to follow the old behavior. Add functions to save and restore old IPv6 method. This is useful when IPv6 is disabled termporarily for the time IPv4 VPN is used. First save the IPv6 method before disabling and call restore when IPv6 needs to be set up again using the old method. --- src/connman.h | 10 +- src/ipconfig.c | 290 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 203 insertions(+), 97 deletions(-) diff --git a/src/connman.h b/src/connman.h index a43a6b8b..1ffce3e1 100644 --- a/src/connman.h +++ b/src/connman.h @@ -340,8 +340,12 @@ void __connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig, const struct connman_ipconfig_ops *ops); int __connman_ipconfig_set_method(struct connman_ipconfig *ipconfig, enum connman_ipconfig_method method); -void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig); -void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig); +void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig, + bool forced); +int __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig, + bool forced); +int __connman_ipconfig_set_ipv6_support(bool enable); +bool __connman_ipconfig_get_ipv6_support(); int __connman_ipconfig_init(void); void __connman_ipconfig_cleanup(void); @@ -406,6 +410,8 @@ void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); enum connman_ipconfig_method __connman_ipconfig_get_method( struct connman_ipconfig *ipconfig); +void __connman_ipconfig_ipv6_method_save(struct connman_ipconfig *ipconfig); +void __connman_ipconfig_ipv6_method_restore(struct connman_ipconfig *ipconfig); int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig); int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig); diff --git a/src/ipconfig.c b/src/ipconfig.c index 2bfeefd4..737e69bc 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -49,12 +49,15 @@ struct connman_ipconfig { void *ops_data; enum connman_ipconfig_method method; + enum connman_ipconfig_method saved_method; struct connman_ipaddress *address; struct connman_ipaddress *system; int ipv6_privacy_config; char *last_dhcp_address; char **last_dhcpv6_prefixes; + + bool ipv6_force_disabled; }; struct connman_ipdevice { @@ -258,153 +261,174 @@ static const char *scope2str(unsigned char scope) return ""; } -static bool get_ipv6_state(gchar *ifname) +#define PROC_IPV4_CONF_PREFIX "/proc/sys/net/ipv4/conf" +#define PROC_IPV6_CONF_PREFIX "/proc/sys/net/ipv6/conf" + +static int read_conf_value(const char *prefix, const char *ifname, + const char *suffix, int *value) { - int disabled; gchar *path; FILE *f; - bool enabled = false; - - if (!ifname) - path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6"); - else - path = g_strdup_printf( - "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname); + int err; + path = g_build_filename(prefix, ifname ? ifname : "all", suffix, NULL); if (!path) - return enabled; + return -ENOMEM; + errno = 0; f = fopen(path, "r"); + if (!f) { + err = -errno; + } else { + errno = 0; /* Avoid stale errno values with fscanf */ - g_free(path); + err = fscanf(f, "%d", value); + if (err <= 0 && errno) + err = -errno; - if (f) { - if (fscanf(f, "%d", &disabled) > 0) - enabled = !disabled; fclose(f); } - return enabled; + if (err <= 0) + connman_error("failed to read %s", path); + + g_free(path); + + return err; } -static void set_ipv6_state(gchar *ifname, bool enable) +static int read_ipv4_conf_value(const char *ifname, const char *suffix, + int *value) { + return read_conf_value(PROC_IPV4_CONF_PREFIX, ifname, suffix, value); +} + +static int read_ipv6_conf_value(const char *ifname, const char *suffix, + int *value) +{ + return read_conf_value(PROC_IPV6_CONF_PREFIX, ifname, suffix, value); +} + +static int write_conf_value(const char *prefix, const char *ifname, + const char *suffix, int value) { gchar *path; FILE *f; + int rval; - if (!ifname) - path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6"); - else - path = g_strdup_printf( - "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname); - + path = g_build_filename(prefix, ifname ? ifname : "all", suffix, NULL); if (!path) - return; + return -ENOMEM; f = fopen(path, "r+"); + if (!f) { + rval = -errno; + } else { + rval = fprintf(f, "%d", value); + fclose(f); + } + + if (rval <= 0) + connman_error("failed to set %s value %d", path, value); g_free(path); - if (!f) - return; + return rval; +} - if (!enable) - fprintf(f, "1"); - else - fprintf(f, "0"); +static int write_ipv4_conf_value(const char *ifname, const char *suffix, + int value) +{ + return write_conf_value(PROC_IPV4_CONF_PREFIX, ifname, suffix, value); +} - fclose(f); +static int write_ipv6_conf_value(const char *ifname, const char *suffix, + int value) +{ + return write_conf_value(PROC_IPV6_CONF_PREFIX, ifname, suffix, value); } -static int get_ipv6_privacy(gchar *ifname) +static bool get_ipv6_state(gchar *ifname) { - gchar *path; - FILE *f; - int value; + int disabled; + bool enabled = false; - if (!ifname) - return 0; + if (read_ipv6_conf_value(ifname, "disable_ipv6", &disabled) > 0) + enabled = !disabled; - path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr", - ifname); + return enabled; +} - if (!path) - return 0; +static int set_ipv6_state(gchar *ifname, bool enable) +{ + int disabled = enable ? 0 : 1; - f = fopen(path, "r"); + DBG("%s %d", ifname, disabled); - g_free(path); + return write_ipv6_conf_value(ifname, "disable_ipv6", disabled); +} - if (!f) +static int get_ipv6_privacy(gchar *ifname) +{ + int value; + + if (!ifname) return 0; - if (fscanf(f, "%d", &value) <= 0) + if (read_ipv6_conf_value(ifname, "use_tempaddr", &value) < 0) value = 0; - fclose(f); - return value; } /* Enable the IPv6 privacy extension for stateless address autoconfiguration. * The privacy extension is described in RFC 3041 and RFC 4941 */ -static void set_ipv6_privacy(gchar *ifname, int value) +static int set_ipv6_privacy(gchar *ifname, int value) { - gchar *path; - FILE *f; - if (!ifname) - return; - - path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr", - ifname); - - if (!path) - return; + return -EINVAL; if (value < 0) value = 0; - f = fopen(path, "r+"); + return write_ipv6_conf_value(ifname, "use_tempaddr", value); +} - g_free(path); +static int set_ipv6_autoconf(gchar *ifname, bool enable) +{ + int value = enable ? 1 : 0; - if (!f) - return; + DBG("%s %d", ifname, enable); - fprintf(f, "%d", value); - fclose(f); + return write_ipv6_conf_value(ifname, "autoconf", value); } static int get_rp_filter(void) { - FILE *f; - int value = -EINVAL, tmp; - - f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r"); + int value; - if (f) { - if (fscanf(f, "%d", &tmp) == 1) - value = tmp; - fclose(f); - } + if (read_ipv4_conf_value(NULL, "rp_filter", &value) < 0) + value = -EINVAL; return value; } -static void set_rp_filter(int value) +static int set_rp_filter(int value) { - FILE *f; - - f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+"); - - if (!f) - return; - - fprintf(f, "%d", value); + /* 0 = no validation, 1 = strict mode, 2 = loose mode */ + switch (value) { + case -1: + value = 0; + /* fall through */ + case 0: + case 1: + case 2: + break; + default: + return -EINVAL; + } - fclose(f); + return write_ipv4_conf_value(NULL, "rp_filter", value); } int __connman_ipconfig_set_rp_filter() @@ -448,6 +472,13 @@ bool __connman_ipconfig_ipv6_is_enabled(struct connman_ipconfig *ipconfig) if (!ipconfig) return false; + /* + * Return forced value since kernel can enable LL address for IPv6 + * for handling ICMPv6. + */ + if (ipconfig->ipv6_force_disabled) + return false; + ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); if (!ipdevice) @@ -1236,6 +1267,8 @@ static struct connman_ipconfig *create_ipv6config(int index) else ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO; + ipv6config->saved_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; + ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); if (ipdevice) ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy; @@ -1421,6 +1454,33 @@ enum connman_ipconfig_method __connman_ipconfig_get_method( return ipconfig->method; } +void __connman_ipconfig_ipv6_method_save(struct connman_ipconfig *ipconfig) +{ + if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) + return; + + DBG("%p method %d", ipconfig, ipconfig->method); + + ipconfig->saved_method = ipconfig->method; +} + +void __connman_ipconfig_ipv6_method_restore(struct connman_ipconfig *ipconfig) +{ + if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) + return; + + /* If not previously set, default to AUTO */ + if (ipconfig->saved_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN) + ipconfig->method = CONNMAN_IPCONFIG_METHOD_AUTO; + else + ipconfig->method = ipconfig->saved_method; + + DBG("%p saved method %d set method %d", ipconfig, + ipconfig->saved_method, ipconfig->method); + + ipconfig->saved_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; +} + int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig) { switch (ipconfig->method) { @@ -1567,7 +1627,7 @@ char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig *ipconfig) return ipconfig->last_dhcpv6_prefixes; } -static void disable_ipv6(struct connman_ipconfig *ipconfig) +static int disable_ipv6(struct connman_ipconfig *ipconfig, bool forced) { struct connman_ipdevice *ipdevice; char *ifname; @@ -1577,16 +1637,26 @@ static void disable_ipv6(struct connman_ipconfig *ipconfig) ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); if (!ipdevice) - return; + return -EINVAL; + + DBG("%p forced %s force_disabled %s", ipconfig, forced ? "yes" : "no", + ipconfig->ipv6_force_disabled ? "yes" : "no"); ifname = connman_inet_ifname(ipconfig->index); set_ipv6_state(ifname, false); + if (forced) { + set_ipv6_autoconf(ifname, false); + ipconfig->ipv6_force_disabled = true; + } + g_free(ifname); + + return 0; } -static void enable_ipv6(struct connman_ipconfig *ipconfig) +static int enable_ipv6(struct connman_ipconfig *ipconfig, bool forced) { struct connman_ipdevice *ipdevice; char *ifname; @@ -1596,7 +1666,17 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); if (!ipdevice) - return; + return -EINVAL; + + DBG("IPv6 %s %p forced %s force_disabled %s", + is_ipv6_supported ? "on" : "off", ipconfig, + forced ? "yes" : "no", + ipconfig->ipv6_force_disabled ? "yes" : "no"); + + if ((!is_ipv6_supported || ipconfig->ipv6_force_disabled) && !forced) + return -EOPNOTSUPP; + + ipconfig->ipv6_force_disabled = false; ifname = connman_inet_ifname(ipconfig->index); @@ -1605,23 +1685,42 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) set_ipv6_state(ifname, true); + if (forced) + set_ipv6_autoconf(ifname, true); + g_free(ifname); + + return 0; } -void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig) +int __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig, + bool forced) { if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) - return; + return -EINVAL; - enable_ipv6(ipconfig); + return enable_ipv6(ipconfig, forced); } -void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig) +void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig, + bool forced) { if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) return; - disable_ipv6(ipconfig); + disable_ipv6(ipconfig, forced); +} + +int __connman_ipconfig_set_ipv6_support(bool enable) +{ + is_ipv6_supported = enable ? connman_inet_is_ipv6_supported() : false; + + return 0; +} + +bool __connman_ipconfig_get_ipv6_support() +{ + return is_ipv6_supported; } bool __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig) @@ -1650,6 +1749,7 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) bool lower_up = false, lower_down = false; enum connman_ipconfig_type type; char *ifname; + int err; DBG("ipconfig %p", ipconfig); @@ -1703,7 +1803,9 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { ipdevice->config_ipv6 = __connman_ipconfig_ref(ipconfig); - enable_ipv6(ipdevice->config_ipv6); + err = enable_ipv6(ipdevice->config_ipv6, false); + if (err) + return err; } ipconfig_list = g_list_append(ipconfig_list, ipconfig); @@ -1872,9 +1974,7 @@ int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig, ipconfig->ipv6_privacy_config = privacy; - enable_ipv6(ipconfig); - - return 0; + return enable_ipv6(ipconfig, false); } void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, -- 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 7 **************************************