[PATCH v2 27/42] wireguard: Set split routing based on AllowedIPs

Jussi Laakkonen <[email protected]> Wed, 13 Aug 2025 18:01:59 +0300
Newsgroups dev.linux.lists.connman
Message-ID <[email protected]>
Split routing value must be set with WireGuard according to the IP
ranges set with AllowedIPs option. If the option contains an any IP
range (INADDR_ANY/IN6ADDR_ANY_INIT, i.e. 0.0.0.0/0 or ::/0) split
routing must be off since the configuration indicates that the
connection is to be used as the route for all traffic. Similarly,
if there is no any IP range split routing is enabled as only the IP
ranges defined are being encrypted and processed according to the
cryptokey routing table configured on the endpoint.

Also fix a memleak in parse_allowed_ips().
---
 vpn/plugins/wireguard.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/vpn/plugins/wireguard.c b/vpn/plugins/wireguard.c
index 2531fff6..271b57b2 100644
--- a/vpn/plugins/wireguard.c
+++ b/vpn/plugins/wireguard.c
@@ -134,7 +134,8 @@ static int parse_key(const char *str, wg_key key)
 	return 0;
 }
 
-static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
+static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer,
+							bool *do_split_routing)
 {
 	struct wg_allowedip *curaip, *allowedip;
 	char buf[INET6_ADDRSTRLEN];
@@ -142,6 +143,7 @@ static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
 	char *send;
 	int i;
 
+	*do_split_routing = true;
 	curaip = NULL;
 	tokens = g_strsplit(allowed_ips, ", ", -1);
 	for (i = 0; tokens[i]; i++) {
@@ -169,6 +171,16 @@ static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
 
 		allowedip->cidr = g_ascii_strtoull(toks[1], &send, 10);
 
+		/*
+		 * Force split routing off if any address is detected as using
+		 * these as allowed IPs indicates that WireGuard is to be used
+		 * to route all traffic.
+		 */
+		if (connman_inet_is_any_addr(toks[0], allowedip->family))
+			*do_split_routing = false;
+
+		g_strfreev(toks);
+
 		if (!curaip)
 			peer->first_allowedip = allowedip;
 		else
@@ -579,6 +591,7 @@ static int wg_connect(struct vpn_provider *provider,
 	struct wireguard_info *info;
 	const char *option, *gateway;
 	char *ifname;
+	bool do_split_routing = true;
 	int err = -EINVAL;
 
 	info = create_private_data(provider);
@@ -641,12 +654,15 @@ static int wg_connect(struct vpn_provider *provider,
 		DBG("WireGuard.AllowedIPs is missing");
 		goto error;
 	}
-	err = parse_allowed_ips(option, &info->peer);
+	err = parse_allowed_ips(option, &info->peer, &do_split_routing);
 	if (err) {
 		DBG("Failed to parse allowed IPs %s", option);
 		goto error;
 	}
 
+	vpn_provider_set_boolean(provider, "SplitRouting", do_split_routing,
+							false);
+
 	option = vpn_provider_get_string(provider,
 					"WireGuard.PersistentKeepalive");
 	if (option) {
-- 
2.39.5