diff options
author | Jussi Laakkonen <jussi.laakkonen@jolla.com> | 2020-12-08 12:17:56 +0200 |
---|---|---|
committer | Daniel Wagner <wagi@monom.org> | 2020-12-11 14:29:10 +0100 |
commit | 0931adf7c5942f4aee494b68365a5244b7d23225 (patch) | |
tree | 24ab751e50b14603731820e1d7e9f62fc5bee236 | |
parent | 57f79c761be9ae005ffad74ee85fd4349e2428f6 (diff) | |
download | connman-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.h | 4 | ||||
-rw-r--r-- | src/provider.c | 101 |
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; |