[PATCH v2 24/42] vpn: Add support for dual-IP VPNs
Jussi Laakkonen <[email protected]> Wed, 13 Aug 2025 18:01:56 +0300
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <[email protected]> |
Information sent by vpn-provider.c on dual-IP VPNs must be handled also
here properly. Adapt to using modified connman_provider_get_family().
Use with the modified connman_provider_get_family() to query which
families are supported to clean up the code.
---
plugins/vpn.c | 126 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 84 insertions(+), 42 deletions(-)
diff --git a/plugins/vpn.c b/plugins/vpn.c
index c0739fc1..97ca72c5 100644
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -1554,57 +1554,94 @@ static void set_route(struct connection_data *data, struct vpn_route *route)
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)
+
+static int set_network_route(struct connection_data *data, struct vpn_route *rt)
{
- struct vpn_route rt = { 0, };
int err;
- if (!data)
- return -EINVAL;
-
- rt.family = connman_provider_get_family(data->provider);
- switch (rt.family) {
- case PF_INET:
- err = connman_inet_get_route_addresses(data->index,
- &rt.network, &rt.netmask, &rt.gateway);
- break;
- case PF_INET6:
- err = connman_inet_ipv6_get_route_addresses(data->index,
- &rt.network, &rt.netmask, &rt.gateway);
- break;
- default:
- connman_error("invalid protocol family %d", rt.family);
+ if (!data || !rt)
return -EINVAL;
- }
DBG("network %s gateway %s netmask %s for provider %p",
- rt.network, rt.gateway, rt.netmask,
- data->provider);
+ rt->network, rt->gateway, rt->netmask,
+ data->provider);
- if (err) {
- connman_error("cannot get network/gateway/netmask for %p",
- data->provider);
- goto out;
- }
-
- err = save_route(data->server_routes, rt.family, rt.network, rt.netmask,
- rt.gateway);
+ err = save_route(data->server_routes, rt->family, rt->network,
+ rt->netmask, rt->gateway);
if (err) {
connman_warn("failed to add network route for provider"
"%p", data->provider);
- goto out;
+ return err;
}
- set_route(data, &rt);
-
-out:
- g_free(rt.network);
- g_free(rt.netmask);
- g_free(rt.gateway);
+ set_route(data, rt);
return 0;
}
+static void free_network_route(struct vpn_route *rt)
+{
+ g_free(rt->network);
+ rt->network = NULL;
+
+ g_free(rt->netmask);
+ rt->network = NULL;
+
+ g_free(rt->gateway);
+ rt->network = NULL;
+}
+
+static int add_network_route(struct connection_data *data)
+{
+ struct vpn_route rt = { 0, };
+ int err = 0;
+
+ if (!data)
+ return -EINVAL;
+
+ if (connman_provider_get_family(data->provider, AF_INET)) {
+ rt.family = AF_INET;
+ err = connman_inet_get_route_addresses(data->index,
+ &rt.network, &rt.netmask,
+ &rt.gateway);
+ if (err) {
+ connman_error("cannot get IPv4 network/gateway/netmask "
+ "for %p/%s", data->provider,
+ data->ident);
+ } else {
+ err = set_network_route(data, &rt);
+ if (err)
+ connman_error("cannot set IPv4 network route "
+ "for %p/%s", data->provider,
+ data->ident);
+ }
+
+ free_network_route(&rt);
+ }
+
+ if (connman_provider_get_family(data->provider, AF_INET6)) {
+ rt.family = AF_INET6;
+ err = connman_inet_ipv6_get_route_addresses(data->index,
+ &rt.network, &rt.netmask,
+ &rt.gateway);
+ if (err) {
+ connman_error("cannot get IPv6 network/gateway/netmask "
+ "for %p/%s", data->provider,
+ data->ident);
+ } else {
+ err = set_network_route(data, &rt);
+ if (err)
+ connman_error("cannot set IPv6 network route "
+ "for %p/%s", data->provider,
+ data->ident);
+ }
+
+ free_network_route(&rt);
+ }
+
+ return err;
+}
+
static bool is_valid_route_table(struct connman_provider *provider,
GHashTable *table)
{
@@ -1667,6 +1704,14 @@ static bool check_routes(struct connman_provider *provider)
return false;
}
+static void set_default_route(struct connection_data *data, int family,
+ char *ipaddr_any)
+{
+ struct vpn_route def_route = {family, ipaddr_any, ipaddr_any, NULL};
+
+ set_route(data, &def_route);
+}
+
static int set_routes(struct connman_provider *provider,
enum connman_provider_route_type type)
{
@@ -1699,13 +1744,10 @@ static int set_routes(struct connman_provider *provider,
/* 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};
-
- set_route(data, &def_route);
+ if (connman_provider_get_family(provider, AF_INET))
+ set_default_route(data, AF_INET, "0.0.0.0");
+ if (connman_provider_get_family(provider, AF_INET6))
+ set_default_route(data, AF_INET6, "::");
}
/* Split routed VPN must have at least one route to the network */
--
2.39.5