Send connman mailing list submissions to
[email protected]
To subscribe or unsubscribe via email, send a message with subject or
body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."
Today's Topics:
1. [PATCH 07/15] service: Expose set_split_routing() for internal use
(Jussi Laakkonen)
2. [PATCH 08/15] service: Add property changed signal for SplitRouting value
(Jussi Laakkonen)
3. [PATCH 09/15] service: Load and apply service settings after D-Bus
registration
(Jussi Laakkonen)
4. [PATCH 10/15] provider: Add support for managing SplitRouting
(Jussi Laakkonen)
5. [PATCH 11/15] vpn: Support SplitRouting in D-Bus variables, improve route
code
(Jussi Laakkonen)
----------------------------------------------------------------------
Date: Tue, 8 Dec 2020 12:17:53 +0200
From: Jussi Laakkonen <[email protected]>
Subject: [PATCH 07/15] service: Expose set_split_routing() for
internal use
To: [email protected]
Message-ID: <[email protected]>
Rename set_split_routing() to __connman_service_set_split_routing() to
be used outside service.c.
---
src/connman.h | 2 ++
src/service.c | 23 +++++++++++++----------
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/src/connman.h b/src/connman.h
index c9820d26..dddb399f 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -784,6 +784,8 @@ void __connman_service_set_pac(struct connman_service
*service,
bool __connman_service_is_hidden(struct connman_service *service);
bool __connman_service_is_split_routing(struct connman_service *service);
bool __connman_service_index_is_split_routing(int index);
+void __connman_service_set_split_routing(struct connman_service *service,
+ bool split_routing);
int __connman_service_get_index(struct connman_service *service);
void __connman_service_set_hidden(struct connman_service *service);
void __connman_service_set_hostname(struct connman_service *service,
diff --git a/src/service.c b/src/service.c
index fd04d65e..9fd7e478 100644
--- a/src/service.c
+++ b/src/service.c
@@ -367,7 +367,8 @@ static enum connman_service_proxy_method
string2proxymethod(const char *method)
return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
}
-static void set_split_routing(struct connman_service *service, bool value)
+void __connman_service_set_split_routing(struct connman_service *service,
+ bool value)
{
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
return;
@@ -400,9 +401,10 @@ int __connman_service_load_modifiable(struct
connman_service *service)
case CONNMAN_SERVICE_TYPE_P2P:
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
/* fall through */
case CONNMAN_SERVICE_TYPE_WIFI:
@@ -456,9 +458,10 @@ static int service_load(struct connman_service *service)
case CONNMAN_SERVICE_TYPE_P2P:
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
autoconnect = g_key_file_get_boolean(keyfile,
service->identifier, "AutoConnect", &error);
@@ -4793,11 +4796,11 @@ int __connman_service_move(struct connman_service
*service,
return -EINVAL;
}
- set_split_routing(target, true);
+ __connman_service_set_split_routing(target, true);
} else
- set_split_routing(target, false);
+ __connman_service_set_split_routing(target, false);
- set_split_routing(service, false);
+ __connman_service_set_split_routing(service, false);
target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
--
2.20.1
------------------------------
Date: Tue, 8 Dec 2020 12:17:54 +0200
From: Jussi Laakkonen <[email protected]>
Subject: [PATCH 08/15] service: Add property changed signal for
SplitRouting value
To: [email protected]
Message-ID: <[email protected]>
Send property changed signal when setting SplitRouting value for a VPN
service. This allows vpnd, and other components using the Service D-Bus
API, to keep track on the changes also when the service ordering
changes the value. Since the split routing value is by default false at
startup and reading no/false value from settings file would not
otherwise trigger the signal it is useful to always send the signal.
Added function __connman_service_split_routing_changed() to be used when
externally managing the value. For example, when the value is not
changed because of missing routes when doing the service move this
function can be used by the external component to indicate the current
status of split routing.
---
src/connman.h | 1 +
src/service.c | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/src/connman.h b/src/connman.h
index dddb399f..12e9407f 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -786,6 +786,7 @@ bool __connman_service_is_split_routing(struct
connman_service *service);
bool __connman_service_index_is_split_routing(int index);
void __connman_service_set_split_routing(struct connman_service *service,
bool split_routing);
+void __connman_service_split_routing_changed(struct connman_service *service);
int __connman_service_get_index(struct connman_service *service);
void __connman_service_set_hidden(struct connman_service *service);
void __connman_service_set_hostname(struct connman_service *service,
diff --git a/src/service.c b/src/service.c
index 9fd7e478..bac044a8 100644
--- a/src/service.c
+++ b/src/service.c
@@ -367,6 +367,24 @@ static enum connman_service_proxy_method
string2proxymethod(const char *method)
return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
}
+void __connman_service_split_routing_changed(struct connman_service *service)
+{
+ dbus_bool_t split_routing;
+
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+ split_routing = service->do_split_routing;
+ if (!connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing))
+ connman_warn("cannot send SplitRouting property change on %s",
+ service->identifier);
+}
+
void __connman_service_set_split_routing(struct connman_service *service,
bool value)
{
@@ -379,6 +397,12 @@ void __connman_service_set_split_routing(struct
connman_service *service,
service->order = 0;
else
service->order = 10;
+
+ /*
+ * In order to make sure the value is propagated also when loading the
+ * VPN service signal the value regardless of the value change.
+ */
+ __connman_service_split_routing_changed(service);
}
int __connman_service_load_modifiable(struct connman_service *service)
--
2.20.1
------------------------------
Date: Tue, 8 Dec 2020 12:17:55 +0200
From: Jussi Laakkonen <[email protected]>
Subject: [PATCH 09/15] service: Load and apply service settings after
D-Bus registration
To: [email protected]
Message-ID: <[email protected]>
Change the service registration order to first register the service to
D-Bus and only after that load the service and apply its variables. This
ensures that the values that should be signaled separately, e.g.,
SplitRouting, can be sent. Otherwise the sending of the signal fails as
the path is not registered.
---
src/service.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/service.c b/src/service.c
index bac044a8..f8ea8ebb 100644
--- a/src/service.c
+++ b/src/service.c
@@ -6871,14 +6871,14 @@ static int service_register(struct connman_service
*service)
DBG("path %s", service->path);
- if (__connman_config_provision_service(service) < 0)
- service_load(service);
-
g_dbus_register_interface(connection, service->path,
CONNMAN_SERVICE_INTERFACE,
service_methods, service_signals,
NULL, service, NULL);
+ if (__connman_config_provision_service(service) < 0)
+ service_load(service);
+
service_list_sort();
__connman_connection_update_gateway();
--
2.20.1
------------------------------
Date: Tue, 8 Dec 2020 12:17:56 +0200
From: Jussi Laakkonen <[email protected]>
Subject: [PATCH 10/15] provider: Add support for managing SplitRouting
To: [email protected]
Message-ID: <[email protected]>
Support SplitRouting via provider, add a function for plugins to set the
value: connman_provider_set_split_routing(). In to ensure the proper
handling of split routing value changes utilize the separated service
moving __connman_service_move_service() function to reorder the services
when VPN is connected. When a VPN is to be set as split routed it is
used as a target service, and when VPN is not split routed it should be
regarded as the default service.
If the VPN is not connected only the split routing value is changed for
the service. If there is an error in moving the connected service use
__connman_service_split_routing_changed() to signal vpnd about the
current status of split routing.
To ensure that setting file has the SplitRouting value if changed in VPN
settings by vpnd the vpn_service must be saved. This is to be done
explicitly in provider.c since in service.c the saving is done
explicitly as well after changing the SplitRouting value.
To allow checking the split routing status also in VPN plugin add
connman_provider_is_split_routing() to get the split routing value
from the actual service. By default returns false if the provider or
the service is omitted.
Add getter for provider family: connman_provider_get_family(). Return
AF_UNSPEC with NULL provider.
---
include/provider.h | 4 ++
src/provider.c | 101 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/include/provider.h b/include/provider.h
index b5856653..1f120990 100644
--- a/include/provider.h
+++ b/include/provider.h
@@ -113,6 +113,10 @@ int connman_provider_set_nameservers(struct
connman_provider *provider,
char * const *nameservers);
void connman_provider_set_autoconnect(struct connman_provider *provider,
bool flag);
+bool connman_provider_is_split_routing(struct connman_provider *provider);
+int connman_provider_set_split_routing(struct connman_provider *provider,
+ bool split_routing);
+int connman_provider_get_family(struct connman_provider *provider);
const char *connman_provider_get_driver_name(struct connman_provider
*provider);
const char *connman_provider_get_save_group(struct connman_provider *provider);
diff --git a/src/provider.c b/src/provider.c
index 7d663e0c..1eae4951 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -53,6 +53,7 @@ void __connman_provider_append_properties(struct
connman_provider *provider,
DBusMessageIter *iter)
{
const char *host, *domain, *type;
+ dbus_bool_t split_routing;
if (!provider->driver || !provider->driver->get_property)
return;
@@ -72,6 +73,12 @@ void __connman_provider_append_properties(struct
connman_provider *provider,
if (type)
connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
&type);
+
+ if (provider->vpn_service) {
+ split_routing = connman_provider_is_split_routing(provider);
+ connman_dbus_dict_append_basic(iter, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing);
+ }
}
struct connman_provider *
@@ -597,6 +604,100 @@ void connman_provider_set_autoconnect(struct
connman_provider *provider,
__connman_service_save(provider->vpn_service);
}
+bool connman_provider_is_split_routing(struct connman_provider *provider)
+{
+ if (!provider || !provider->vpn_service)
+ return false;
+
+ return __connman_service_is_split_routing(provider->vpn_service);
+}
+
+int connman_provider_set_split_routing(struct connman_provider *provider,
+ bool split_routing)
+{
+ struct connman_service *service;
+ enum connman_ipconfig_type type;
+ int service_index;
+ int vpn_index;
+ bool service_split_routing;
+ int err = 0;
+
+ DBG("");
+
+ if (!provider || !provider->vpn_service)
+ return -EINVAL;
+
+ service_split_routing = __connman_service_is_split_routing(
+ provider->vpn_service);
+
+ if (service_split_routing == split_routing) {
+ DBG("split_routing already set %s",
+ split_routing ? "true" : "false");
+ return -EALREADY;
+ }
+
+ switch (provider->family) {
+ case AF_INET:
+ type = CONNMAN_IPCONFIG_TYPE_IPV4;
+ break;
+ case AF_INET6:
+ type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ break;
+ case AF_UNSPEC:
+ type = CONNMAN_IPCONFIG_TYPE_ALL;
+ break;
+ default:
+ type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
+ }
+
+ if (!__connman_service_is_connected_state(provider->vpn_service,
+ type)) {
+ DBG("%p VPN not connected", provider->vpn_service);
+ goto save;
+ }
+
+ vpn_index = __connman_service_get_index(provider->vpn_service);
+ service_index = __connman_connection_get_vpn_phy_index(vpn_index);
+ service = __connman_service_lookup_from_index(service_index);
+ if (!service)
+ goto save;
+
+ if (split_routing)
+ err = __connman_service_move(service, provider->vpn_service,
+ true);
+ else
+ err = __connman_service_move(provider->vpn_service, service,
+ true);
+
+ if (err) {
+ connman_warn("cannot move service %p and VPN %p error %d",
+ service, provider->vpn_service, err);
+
+ /*
+ * In case of error notify vpnd about the current split routing
+ * state.
+ */
+ __connman_service_split_routing_changed(provider->vpn_service);
+ goto out;
+ }
+
+save:
+ __connman_service_set_split_routing(provider->vpn_service,
+ split_routing);
+ __connman_service_save(provider->vpn_service);
+
+out:
+ return err;
+}
+
+int connman_provider_get_family(struct connman_provider *provider)
+{
+ if (!provider)
+ return AF_UNSPEC;
+
+ return provider->family;
+}
+
static void unregister_provider(gpointer data)
{
struct connman_provider *provider = data;
--
2.20.1
------------------------------
Date: Tue, 8 Dec 2020 12:17:57 +0200
From: Jussi Laakkonen <[email protected]>
Subject: [PATCH 11/15] vpn: Support SplitRouting in D-Bus variables,
improve route code
To: [email protected]
Message-ID: <[email protected]>
When adding connection check also SplitRouting value and set it
accordingly via provider. Process the SplitRouting variable also when
VPN property changes.
Use the new inet.c functions to get network, netmask and gateway for
VPNs that are split routed that have no other routes set. In that case
add the network route as split routed VPNs must have at least a single
route to VPN network. Check that for non-split routed VPNs the default
route is added and prevent adding default route for split routed VPNs.
Improve check_route() by also checking that the split routed VPN has
more than the default route set. A VPN cannot be set split routed if it
does not have at least one route set.
Always do a route check when changing split routing value via D-Bus. The
check is to make sure that when set as split routed the VPN has at least
one network route set. If not, the functionality described above will
add one.
---
plugins/vpn.c | 227 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 207 insertions(+), 20 deletions(-)
diff --git a/plugins/vpn.c b/plugins/vpn.c
index 3b1b9c8b..be3ad506 100644
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -85,6 +85,7 @@ struct connection_data {
char *domain;
char **nameservers;
bool immutable;
+ bool default_route_set;
GHashTable *server_routes;
GHashTable *user_routes;
@@ -1013,6 +1014,7 @@ static int disconnect_provider(struct connection_data
*data)
g_free(data->service_ident);
data->service_ident = NULL;
+ data->default_route_set = false;
connman_provider_set_state(data->provider,
CONNMAN_PROVIDER_STATE_DISCONNECT);
@@ -1462,6 +1464,17 @@ static void set_route(struct connection_data *data,
struct vpn_route *route)
return;
}
+ DBG("set route provider %p %s/%s/%s", data->provider,
+ route->network, route->gateway,
+ route->netmask);
+
+ /* Do not add default route for split routed VPNs.*/
+ if (connman_provider_is_split_routing(data->provider) &&
+ connman_inet_is_default_route(route->family,
+ route->network, route->gateway,
+ route->netmask))
+ return;
+
if (route->family == AF_INET6) {
unsigned char prefix_len = atoi(route->netmask);
@@ -1474,6 +1487,130 @@ static void set_route(struct connection_data *data,
struct vpn_route *route)
route->gateway,
route->netmask);
}
+
+ if (connman_inet_is_default_route(route->family, route->network,
+ route->gateway, route->netmask))
+ data->default_route_set = true;
+}
+
+static int save_route(GHashTable *routes, int family, const char *network,
+ const char *netmask, const char *gateway);
+
+static int add_network_route(struct connection_data *data)
+{
+ char *network = NULL;
+ char *gateway = NULL;
+ char *netmask = NULL;
+ int family;
+ int err;
+
+ if (!data)
+ return -EINVAL;
+
+ family = connman_provider_get_family(data->provider);
+ switch (family) {
+ case PF_INET:
+ err = connman_inet_get_route_addresses(data->index, &network,
+ &netmask, &gateway);
+ break;
+ case PF_INET6:
+ err = connman_inet_ipv6_get_route_addresses(data->index,
+ &network, &netmask, &gateway);
+ break;
+ default:
+ connman_error("invalid protocol family %d", family);
+ return -EINVAL;
+ }
+
+ DBG("network %s gateway %s netmask %s for provider %p",
+ network, gateway, netmask,
+ data->provider);
+
+ if (err) {
+ connman_error("cannot get network/gateway/netmask for %p",
+ data->provider);
+ goto out;
+ }
+
+ err = save_route(data->server_routes, family, network, netmask,
+ gateway);
+ if (err) {
+ connman_warn("failed to add network route for provider"
+ "%p", data->provider);
+ goto out;
+ }
+
+ struct vpn_route route = { family, network, netmask, gateway };
+ set_route(data, &route);
+
+out:
+ g_free(network);
+ g_free(gateway);
+ g_free(netmask);
+
+ return 0;
+}
+
+static bool is_valid_route_table(struct connman_provider *provider,
+ GHashTable *table)
+{
+ GHashTableIter iter;
+ gpointer value, key;
+ struct vpn_route *route;
+ size_t table_size;
+
+ if (!table)
+ return false;
+
+ table_size = g_hash_table_size(table);
+
+ /* Non-split routed may have only the default route */
+ if (table_size > 0 && !connman_provider_is_split_routing(provider))
+ return true;
+
+ /* Split routed has more than the default route */
+ if (table_size > 1)
+ return true;
+
+ /*
+ * Only one route for split routed VPN, which should not be the
+ * default route.
+ */
+ g_hash_table_iter_init(&iter, table);
+ if (!g_hash_table_iter_next(&iter, &key, &value)) /* First and only */
+ return false;
+
+ route = value;
+ if (!route)
+ return false;
+
+ DBG("check route %d %s/%s/%s", route->family, route->network,
+ route->gateway, route->netmask);
+
+ if (!connman_inet_is_default_route(route->family, route->network,
+ route->gateway, route->netmask))
+ return true;
+
+ return false;
+}
+
+static bool check_routes(struct connman_provider *provider)
+{
+ struct connection_data *data;;
+
+ DBG("provider %p", provider);
+
+ data = connman_provider_get_data(provider);
+ if (!data)
+ return false;
+
+ if (is_valid_route_table(provider, data->user_routes))
+ return true;
+
+ if (is_valid_route_table(provider, data->server_routes))
+ return true;
+
+ return false;
}
static int set_routes(struct connman_provider *provider,
@@ -1505,28 +1642,30 @@ static int set_routes(struct connman_provider *provider,
set_route(data, value);
}
- return 0;
-}
-
-static bool check_routes(struct connman_provider *provider)
-{
- struct connection_data *data;
+ /* If non-split routed VPN does not have a default route, add it */
+ if (!connman_provider_is_split_routing(provider) &&
+ !data->default_route_set) {
+ int family = connman_provider_get_family(provider);
+ const char *ipaddr_any = family == AF_INET6 ?
+ "::" : "0.0.0.0";
+ struct vpn_route def_route = {family, (char*) ipaddr_any,
+ (char*) ipaddr_any, NULL};
- DBG("provider %p", provider);
-
- data = connman_provider_get_data(provider);
- if (!data)
- return false;
-
- if (data->user_routes &&
- g_hash_table_size(data->user_routes) > 0)
- return true;
+ set_route(data, &def_route);
+ }
- if (data->server_routes &&
- g_hash_table_size(data->server_routes) > 0)
- return true;
+ /* Split routed VPN must have at least one route to the network */
+ if (connman_provider_is_split_routing(provider) &&
+ !check_routes(provider)) {
+ int err = add_network_route(data);
+ if (err) {
+ connman_warn("cannot add network route provider %p",
+ provider);
+ return err;
+ }
+ }
- return false;
+ return 0;
}
static struct connman_provider_driver provider_driver = {
@@ -1695,12 +1834,52 @@ static int save_route(GHashTable *routes, int family,
const char *network,
route->gateway = g_strdup(gateway);
g_hash_table_replace(routes, key, route);
- } else
+ } else {
g_free(key);
+ return -EALREADY;
+ }
return 0;
}
+static void change_provider_split_routing(struct connman_provider *provider,
+ bool split_routing)
+{
+ struct connection_data *data;
+ int err;
+
+ if (!provider)
+ return;
+
+ if (connman_provider_is_split_routing(provider) == split_routing)
+ return;
+
+ data = connman_provider_get_data(provider);
+ if (split_routing && data && provider_is_connected(data) &&
+ !check_routes(provider)) {
+ err = add_network_route(data);
+ if (err) {
+ connman_warn("cannot add network route provider %p",
+ provider);
+ return;
+ }
+ }
+
+ err = connman_provider_set_split_routing(provider, split_routing);
+ switch (err) {
+ case 0:
+ /* fall through */
+ case -EALREADY:
+ break;
+ case -EINVAL:
+ /* fall through */
+ case -EOPNOTSUPP:
+ connman_warn("cannot change split routing %d", err);
+ default:
+ break;
+ }
+}
+
static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
{
DBusMessageIter dict;
@@ -1877,6 +2056,10 @@ static gboolean property_changed(DBusConnection *conn,
g_free(data->domain);
data->domain = g_strdup(str);
connman_provider_set_domain(data->provider, data->domain);
+ } else if (g_str_equal(key, "SplitRouting")) {
+ dbus_bool_t split_routing;
+ dbus_message_iter_get_basic(&value, &split_routing);
+ change_provider_split_routing(data->provider, split_routing);
}
if (ip_set && err == 0) {
@@ -1965,6 +2148,10 @@ static void vpn_disconnect_check_provider(struct
connection_data *data)
if (!vpn_is_valid_transport(service)) {
connman_provider_disconnect(data->provider);
}
+
+ /* VPN moved to be split routed, default route is not set */
+ if (connman_provider_is_split_routing(data->provider))
+ data->default_route_set = false;
}
}
--
2.20.1
------------------------------
Subject: Digest Footer
_______________________________________________
connman mailing list -- [email protected]
To unsubscribe send an email to [email protected]
------------------------------
End of connman Digest, Vol 62, Issue 10
***************************************