Commit e59c4189f3 for strongswan.org

commit e59c4189f31903e779595df7b34daec6b2a02a54
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Thu Sep 17 11:22:01 2026 +0200

    kernel-net: Always return global addresses on loopback interfaces

    This changes the interface filters in all kernel backends so that global
    addresses on loopback interfaces are enumerated.  Because Linux and
    FreeBSD default to a weak host model, addresses on any interface are
    usable.  So it's common to install addresses on stable interfaces (e.g.
    `lo`) on systems where interfaces and routes change a lot.

    This is a particular issue for MOBIKE, where we enumerate local addresses
    to send to the peer.  While adding `ADDR_TYPE_LOOPBACK` there would be
    an option, there really is no reason to have that filter now that we
    filter the addresses explicitly (if users want to ignore addresses on
    `lo` for specific setups, they can add it to `interfaces_ignore`).

    Note that the behavior on FreeBSD can be changed via
    `net.inet.ip.rfc1122_strong_es`, and that Windows defaults to the strong
    host model since Vista but can explicitly be changed via `netsh` and
    the `weakhostreceive|send` option.

    The `ADDR_TYPE_LOOPBACK` filter is removed accordingly.

diff --git a/src/libcharon/kernel/kernel_net.h b/src/libcharon/kernel/kernel_net.h
index f24a9510e3..416b60e621 100644
--- a/src/libcharon/kernel/kernel_net.h
+++ b/src/libcharon/kernel/kernel_net.h
@@ -35,18 +35,17 @@ typedef enum kernel_address_type_t kernel_address_type_t;
  * Type of addresses (e.g. when enumerating them)
  */
 enum kernel_address_type_t {
-	/** normal addresses (on regular, up, non-ignored) interfaces */
+	/** addresses on up and non-ignored interfaces, with usable scope and
+	 * non-deprecated, includes globals on loopback interfaces */
 	ADDR_TYPE_REGULAR = (1 << 0),
 	/** addresses on down interfaces */
 	ADDR_TYPE_DOWN =  (1 << 1),
 	/** addresses on ignored interfaces */
 	ADDR_TYPE_IGNORED = (1 << 2),
-	/** addresses on loopback interfaces */
-	ADDR_TYPE_LOOPBACK = (1 << 3),
 	/** virtual IP addresses */
-	ADDR_TYPE_VIRTUAL = (1 << 4),
+	ADDR_TYPE_VIRTUAL = (1 << 3),
 	/** to enumerate all available addresses */
-	ADDR_TYPE_ALL = (1 << 5) - 1,
+	ADDR_TYPE_ALL = (1 << 4) - 1,
 };

 /**
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
index fed5b8fa92..52b231d747 100644
--- a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
@@ -477,11 +477,6 @@ METHOD(enumerator_t, addr_enumerate, bool,
 			{
 				return FALSE;
 			}
-			if (entry->iftype == IF_TYPE_SOFTWARE_LOOPBACK &&
-				!(this->which & ADDR_TYPE_LOOPBACK))
-			{
-				continue;
-			}
 			if (entry->status != IfOperStatusUp &&
 				!(this->which & ADDR_TYPE_DOWN))
 			{
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
index 17910a3057..926d3d9040 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1559,10 +1559,6 @@ CALLBACK(filter_interfaces, bool,
 		{	/* skip interfaces excluded by config */
 			continue;
 		}
-		if (!(data->which & ADDR_TYPE_LOOPBACK) && (iface->flags & IFF_LOOPBACK))
-		{	/* ignore loopback devices */
-			continue;
-		}
 		if (!(data->which & ADDR_TYPE_DOWN) && !(iface->flags & IFF_UP))
 		{	/* skip interfaces not up */
 			continue;
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
index 6fe4371599..b0367ae46a 100644
--- a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -1169,10 +1169,6 @@ CALLBACK(filter_interfaces, bool,
 		{	/* skip interfaces excluded by config */
 			continue;
 		}
-		if (!(data->which & ADDR_TYPE_LOOPBACK) && (iface->flags & IFF_LOOPBACK))
-		{	/* ignore loopback devices */
-			continue;
-		}
 		if (!(data->which & ADDR_TYPE_DOWN) && !(iface->flags & IFF_UP))
 		{	/* skip interfaces not up */
 			continue;