Skip to content

Commit

Permalink
service: Support IPv6 enable/disable for connected services
Browse files Browse the repository at this point in the history
[service] Support IPv6 enable/disable for conn services. JB#53542

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.

Remove unnecessary __connman_service_notify_ipv6_configuration added in
5b7e6fc

Change function name and use bool value as enable - remove negation.

Adapt to network.c changes in __connman_network_enable_ipconfig() to not
to include the force value. Instead use directly
__connman_ipconfig_set_force_disabled_ipv6() to set the ipconfig
internal value.
  • Loading branch information
LaakkonenJussi committed Apr 21, 2021
1 parent 9454f93 commit 36674c8
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 26 deletions.
4 changes: 2 additions & 2 deletions connman/src/connman.h
Expand Up @@ -804,6 +804,8 @@ const char *__connman_service_create(enum connman_service_type type,
const char *ident, GKeyFile *settings);

struct connman_service *__connman_service_lookup_from_index(int index);
void __connman_service_set_ipv6_for_connected(struct connman_service *vpn,
struct connman_service *transport, bool enable);
bool __connman_service_create_from_network(struct connman_network *network);
struct connman_service *__connman_service_create_from_provider(struct connman_provider *provider);
bool __connman_service_index_is_default(int index);
Expand All @@ -820,8 +822,6 @@ struct connman_ipconfig *__connman_service_get_ipconfig(
struct connman_service *service, int family);
void __connman_service_notify_ipv4_configuration(
struct connman_service *service);
void __connman_service_notify_ipv6_configuration(
struct connman_service *service);
bool __connman_service_is_connected_state(struct connman_service *service,
enum connman_ipconfig_type type);
const char *__connman_service_get_path(struct connman_service *service);
Expand Down
148 changes: 124 additions & 24 deletions connman/src/service.c
Expand Up @@ -768,11 +768,12 @@ void __connman_service_set_split_routing(struct connman_service *service,
*/
if (connman_provider_get_family(service->provider) == AF_INET &&
change && is_connected(service)) {
if (__connman_provider_toggle_transport_ipv6(service->provider,
!value))
DBG("cannot toggle IPv6 on transport of service %p"
"provider %p", service,
service->provider);
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);
}

/*
Expand Down Expand Up @@ -2601,15 +2602,6 @@ static void ipv6_configuration_changed(struct connman_service *service)
service);
}

void __connman_service_notify_ipv6_configuration(
struct connman_service *service)
{
if (!service)
return;

ipv6_configuration_changed(service);
}

static void dns_changed(struct connman_service *service)
{
if (!allow_property_changed(service))
Expand Down Expand Up @@ -4885,13 +4877,11 @@ static DBusMessage *set_property(DBusConnection *conn,
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
__connman_network_enable_ipconfig(
service->network,
service->ipconfig_ipv4,
false);
service->ipconfig_ipv4);
else
__connman_network_enable_ipconfig(
service->network,
service->ipconfig_ipv6,
false);
service->ipconfig_ipv6);
}

return __connman_error_failed(msg, -err);
Expand All @@ -4906,13 +4896,11 @@ static DBusMessage *set_property(DBusConnection *conn,
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
__connman_network_enable_ipconfig(
service->network,
service->ipconfig_ipv4,
false);
service->ipconfig_ipv4);
else
__connman_network_enable_ipconfig(
service->network,
service->ipconfig_ipv6,
false);
service->ipconfig_ipv6);
}

service_save(service);
Expand Down Expand Up @@ -7529,8 +7517,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, false);
__connman_ipconfig_disable_ipv6(service->ipconfig_ipv6);

if (connman_setting_get_bool("SingleConnectedTechnology"))
single_connected_tech(service);
Expand Down Expand Up @@ -8946,6 +8933,119 @@ 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) || 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))
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;
Expand Down

0 comments on commit 36674c8

Please sign in to comment.