summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Laakkonen <jussi.laakkonen@jolla.com>2020-12-08 12:17:56 +0200
committerDaniel Wagner <wagi@monom.org>2020-12-11 14:29:10 +0100
commit0931adf7c5942f4aee494b68365a5244b7d23225 (patch)
tree24ab751e50b14603731820e1d7e9f62fc5bee236
parent57f79c761be9ae005ffad74ee85fd4349e2428f6 (diff)
downloadconnman-0931adf7c5942f4aee494b68365a5244b7d23225.tar.gz
provider: Add support for managing SplitRouting
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.
-rw-r--r--include/provider.h4
-rw-r--r--src/provider.c101
2 files changed, 105 insertions, 0 deletions
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;