lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250724150042.6361-3-equinox@diac24.net>
Date: Thu, 24 Jul 2025 17:00:39 +0200
From: David Lamparter <equinox@...c24.net>
To: netdev@...r.kernel.org,
	David Ahern <dsahern@...nel.org>,
	"David S. Miller" <davem@...emloft.net>
Cc: David Lamparter <equinox@...c24.net>,
	Lorenzo Colitti <lorenzo@...gle.com>,
	Patrick Rohr <prohr@...gle.com>
Subject: [PATCH net-next v2 2/4] net/ipv6: create ipv6_fl_get_saddr

This adds passing the relevant flow information as well as selected
nexthop into the source address selection code, to allow the RFC6724
rule 5.5 code to look at its details.

Signed-off-by: David Lamparter <equinox@...c24.net>
---
 include/net/addrconf.h |  4 ++++
 net/ipv6/addrconf.c    | 45 +++++++++++++++++++++++++++++++-----------
 2 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 9e5e95988b9e..952395c198f9 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -141,6 +141,10 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
 int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
 		       const struct in6_addr *daddr, unsigned int srcprefs,
 		       struct in6_addr *saddr);
+int ipv6_fl_get_saddr(struct net *net, const struct dst_entry *dst,
+		      const struct net_device *dst_dev,
+		      const struct sock *sk, unsigned int srcprefs,
+		      struct flowi6 *fl6);
 int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
 		    u32 banned_flags);
 bool inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4f1d7d110302..8ff3aad71466 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1528,7 +1528,9 @@ struct ipv6_saddr_score {
 };
 
 struct ipv6_saddr_dst {
-	const struct in6_addr *addr;
+	const struct flowi6 *fl6;
+	const struct dst_entry *dst;
+	const struct sock *sk;
 	int ifindex;
 	int scope;
 	int label;
@@ -1605,7 +1607,7 @@ static int ipv6_get_saddr_eval(struct net *net,
 		break;
 	case IPV6_SADDR_RULE_LOCAL:
 		/* Rule 1: Prefer same address */
-		ret = ipv6_addr_equal(&score->ifa->addr, dst->addr);
+		ret = ipv6_addr_equal(&score->ifa->addr, &dst->fl6->daddr);
 		break;
 	case IPV6_SADDR_RULE_SCOPE:
 		/* Rule 2: Prefer appropriate scope
@@ -1683,11 +1685,11 @@ static int ipv6_get_saddr_eval(struct net *net,
 		 *	    non-ORCHID vs non-ORCHID
 		 */
 		ret = !(ipv6_addr_orchid(&score->ifa->addr) ^
-			ipv6_addr_orchid(dst->addr));
+			ipv6_addr_orchid(&dst->fl6->daddr));
 		break;
 	case IPV6_SADDR_RULE_PREFIX:
 		/* Rule 8: Use longest matching prefix */
-		ret = ipv6_addr_diff(&score->ifa->addr, dst->addr);
+		ret = ipv6_addr_diff(&score->ifa->addr, &dst->fl6->daddr);
 		if (ret > score->ifa->prefix_len)
 			ret = score->ifa->prefix_len;
 		score->matchlen = ret;
@@ -1805,9 +1807,10 @@ static int ipv6_get_saddr_master(struct net *net,
 	return hiscore_idx;
 }
 
-int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
-		       const struct in6_addr *daddr, unsigned int prefs,
-		       struct in6_addr *saddr)
+int ipv6_fl_get_saddr(struct net *net, const struct dst_entry *dst_entry,
+		      const struct net_device *dst_dev,
+		      const struct sock *sk, unsigned int prefs,
+		      struct flowi6 *fl6)
 {
 	struct ipv6_saddr_score scores[2], *hiscore;
 	struct ipv6_saddr_dst dst;
@@ -1818,11 +1821,13 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
 	int hiscore_idx = 0;
 	int ret = 0;
 
-	dst_type = __ipv6_addr_type(daddr);
-	dst.addr = daddr;
+	dst_type = __ipv6_addr_type(&fl6->daddr);
+	dst.fl6 = fl6;
+	dst.sk = sk;
+	dst.dst = dst_entry;
 	dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
 	dst.scope = __ipv6_addr_src_scope(dst_type);
-	dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex);
+	dst.label = ipv6_addr_label(net, &fl6->daddr, dst_type, dst.ifindex);
 	dst.prefs = prefs;
 
 	scores[hiscore_idx].rule = -1;
@@ -1897,11 +1902,29 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
 	if (!hiscore->ifa)
 		ret = -EADDRNOTAVAIL;
 	else
-		*saddr = hiscore->ifa->addr;
+		fl6->saddr = hiscore->ifa->addr;
 
 	rcu_read_unlock();
 	return ret;
 }
+EXPORT_SYMBOL(ipv6_fl_get_saddr);
+
+int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
+		       const struct in6_addr *daddr, unsigned int prefs,
+		       struct in6_addr *saddr)
+{
+	struct flowi6 fl6;
+	int ret;
+
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.daddr = *daddr;
+
+	ret = ipv6_fl_get_saddr(net, NULL, dst_dev, NULL, prefs, &fl6);
+	if (!ret)
+		*saddr = fl6.saddr;
+
+	return ret;
+}
 EXPORT_SYMBOL(ipv6_dev_get_saddr);
 
 static int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
-- 
2.47.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ