[PATCH v2 23/42] provider: Add support for dual-IP VPNs
Jussi Laakkonen <[email protected]> Wed, 13 Aug 2025 18:01:55 +0300
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <[email protected]> |
Handle both IP family types for a VPN if it, like WireGuard, has them.
Change the functionality regarding supported families to use a boolean
array defining which address families are supported by a VPN.
Modify the connman_provider_get_family() to be a query type based on the
AF given.
---
include/provider.h | 2 +-
src/provider.c | 88 +++++++++++++++++++++++++++++++++-------------
2 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/include/provider.h b/include/provider.h
index aac47527..3e6ea2c7 100644
--- a/include/provider.h
+++ b/include/provider.h
@@ -117,7 +117,7 @@ void connman_provider_set_autoconnect(struct connman_provider *provider,
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);
+bool connman_provider_get_family(struct connman_provider *provider, int family);
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 d7218420..d677aa12 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -31,6 +31,7 @@
#include <gweb/gresolv.h>
#include "connman.h"
+#include "src/shared/util.h"
static DBusConnection *connection = NULL;
@@ -44,11 +45,35 @@ struct connman_provider {
struct connman_service *vpn_service;
int index;
char *identifier;
- int family;
+ struct supported_afs family;
struct connman_provider_driver *driver;
void *driver_data;
};
+static void provider_set_family(struct connman_provider *provider, int family)
+{
+ if (!provider)
+ return;
+
+ util_set_afs(&provider->family, family);
+}
+
+static bool provider_get_family(struct connman_provider *provider, int family)
+{
+ if (!provider)
+ return false;
+
+ return util_get_afs(&provider->family, family);
+}
+
+static void provider_reset_family(struct connman_provider *provider)
+{
+ if (!provider)
+ return;
+
+ util_reset_afs(&provider->family);
+}
+
void __connman_provider_append_properties(struct connman_provider *provider,
DBusMessageIter *iter)
{
@@ -158,6 +183,8 @@ int connman_provider_disconnect(struct connman_provider *provider)
provider_indicate_state(provider,
CONNMAN_SERVICE_STATE_IDLE);
+ provider_reset_family(provider);
+
return 0;
}
@@ -245,22 +272,36 @@ static int set_connected(struct connman_provider *provider,
bool connected)
{
struct connman_service *service = provider->vpn_service;
- struct connman_ipconfig *ipconfig;
+ struct connman_ipconfig *ipconfig_ipv4 = NULL;
+ struct connman_ipconfig *ipconfig_ipv6 = NULL;
if (!service)
return -ENODEV;
- ipconfig = __connman_service_get_ipconfig(service, provider->family);
+ if (provider_get_family(provider, AF_INET))
+ ipconfig_ipv4 = __connman_service_get_ipconfig(service,
+ AF_INET);
+
+ if (provider_get_family(provider, AF_INET6))
+ ipconfig_ipv6 = __connman_service_get_ipconfig(service,
+ AF_INET6);
if (connected) {
- if (!ipconfig) {
+ if (!ipconfig_ipv4 && !ipconfig_ipv6) {
provider_indicate_state(provider,
CONNMAN_SERVICE_STATE_FAILURE);
return -EIO;
}
- __connman_ipconfig_address_add(ipconfig);
- __connman_ipconfig_gateway_add(ipconfig);
+ if (ipconfig_ipv4) {
+ __connman_ipconfig_address_add(ipconfig_ipv4);
+ __connman_ipconfig_gateway_add(ipconfig_ipv4);
+ }
+
+ if (ipconfig_ipv6) {
+ __connman_ipconfig_address_add(ipconfig_ipv6);
+ __connman_ipconfig_gateway_add(ipconfig_ipv6);
+ }
provider_indicate_state(provider,
CONNMAN_SERVICE_STATE_READY);
@@ -270,10 +311,16 @@ static int set_connected(struct connman_provider *provider,
CONNMAN_PROVIDER_ROUTE_ALL);
} else {
- if (ipconfig) {
+ if (ipconfig_ipv4) {
provider_indicate_state(provider,
CONNMAN_SERVICE_STATE_DISCONNECT);
- __connman_ipconfig_gateway_remove(ipconfig);
+ __connman_ipconfig_gateway_remove(ipconfig_ipv4);
+ }
+
+ if (ipconfig_ipv6) {
+ provider_indicate_state(provider,
+ CONNMAN_SERVICE_STATE_DISCONNECT);
+ __connman_ipconfig_gateway_remove(ipconfig_ipv6);
}
provider_indicate_state(provider,
@@ -557,7 +604,7 @@ int connman_provider_set_ipaddress(struct connman_provider *provider,
if (!ipconfig)
return -EINVAL;
- provider->family = ipaddress->family;
+ provider_set_family(provider, ipaddress->family);
__connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_FIXED);
@@ -652,19 +699,15 @@ int connman_provider_set_split_routing(struct connman_provider *provider,
return -EALREADY;
}
- switch (provider->family) {
- case AF_INET:
+ if (provider_get_family(provider, AF_INET) &&
+ provider_get_family(provider, AF_INET6))
+ type = CONNMAN_IPCONFIG_TYPE_ALL;
+ else if (provider_get_family(provider, AF_INET))
type = CONNMAN_IPCONFIG_TYPE_IPV4;
- break;
- case AF_INET6:
+ else if (provider_get_family(provider, AF_INET6))
type = CONNMAN_IPCONFIG_TYPE_IPV6;
- break;
- case AF_UNSPEC:
- type = CONNMAN_IPCONFIG_TYPE_ALL;
- break;
- default:
+ else
type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
- }
if (!__connman_service_is_connected_state(provider->vpn_service,
type)) {
@@ -706,12 +749,9 @@ out:
return err;
}
-int connman_provider_get_family(struct connman_provider *provider)
+bool connman_provider_get_family(struct connman_provider *provider, int family)
{
- if (!provider)
- return AF_UNSPEC;
-
- return provider->family;
+ return provider_get_family(provider, family);
}
static void unregister_provider(gpointer data)
--
2.39.5