]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
libipsec: Also install routes without preferred source to forward traffic
authorBoi Sletterink <boi@sletterink.nl>
Thu, 29 Jun 2023 15:39:37 +0000 (17:39 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 4 Sep 2023 14:54:37 +0000 (16:54 +0200)
Fixes a problem installing policies with source traffic selectors that do
not contain/match any of the local addresses.

When installing a route for a source TS that does contain one or more
local addresses, a preferred source address should be set in the route
(analogous to the `src` option in `ip route add`). This address is used
when the host itself sends traffic via that route (in contrast to
forwarding it).

When the source TS does not encompass any of the local addresses, the
host is not allowed to send traffic via this route and does not need to
set the preferred source address. However, the code would just return a
failure because it could not find a matching local address. This commit
changes this so routes without preferred source IP are installed to
allow non-local traffic to get forwarded via TUN device.

Closes strongswan/strongswan#1766

src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c

index 22e1200dd99019933a4fc295154fa3a650be943c..cf35592fd8a2133bd1f4823babb70d41e173d9a8 100644 (file)
@@ -419,8 +419,10 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
        {
                traffic_selector_t *multicast, *broadcast = NULL;
                bool ignore = FALSE;
+               int family;
 
-               this->mutex->unlock(this->mutex);
+               /* ignore multi- and broadcast TS, othewise, install a route without
+                * preferred source IP to forward non-local traffic via TUN device */
                switch (src_ts->get_type(src_ts))
                {
                        case TS_IPV4_ADDR_RANGE:
@@ -428,24 +430,27 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
                                                                                                                          0, 0, 0xffff);
                                broadcast = traffic_selector_create_from_cidr("255.255.255.255/32",
                                                                                                                          0, 0, 0xffff);
+                               family = AF_INET;
                                break;
                        case TS_IPV6_ADDR_RANGE:
                                multicast = traffic_selector_create_from_cidr("ff00::/8",
                                                                                                                          0, 0, 0xffff);
+                               family = AF_INET6;
                                break;
                        default:
+                               this->mutex->unlock(this->mutex);
                                return FALSE;
                }
                ignore = src_ts->is_contained_in(src_ts, multicast);
                ignore |= broadcast && src_ts->is_contained_in(src_ts, broadcast);
                multicast->destroy(multicast);
                DESTROY_IF(broadcast);
-               if (!ignore)
+               if (ignore)
                {
-                       DBG1(DBG_KNL, "error installing route with policy %R === %R %N",
-                                src_ts, dst_ts, policy_dir_names, policy->direction);
+                       this->mutex->unlock(this->mutex);
+                       return TRUE;
                }
-               return ignore;
+               src_ip = host_create_any(family);
        }
 
        INIT(route,