summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEyal Birger <eyal.birger@gmail.com>2024-09-03 03:07:10 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-11-01 04:02:35 +0300
commitb50a8de9a42e42bf14b352cb2317b6606c9860a7 (patch)
tree221991fd0893083f33322fd0530ec21110a73fa0
parent62e5a6a4366c5d5856054ff790cffc38a5e5fa31 (diff)
downloadlinux-b50a8de9a42e42bf14b352cb2317b6606c9860a7.tar.xz
xfrm: respect ip protocols rules criteria when performing dst lookups
[ Upstream commit b8469721034300bbb6dec5b4bf32492c95e16a0c ] The series in the "fixes" tag added the ability to consider L4 attributes in routing rules. The dst lookup on the outer packet of encapsulated traffic in the xfrm code was not adapted to this change, thus routing behavior that relies on L4 information is not respected. Pass the ip protocol information when performing dst lookups. Fixes: a25724b05af0 ("Merge branch 'fib_rules-support-sport-dport-and-proto-match'") Signed-off-by: Eyal Birger <eyal.birger@gmail.com> Tested-by: Antony Antony <antony.antony@secunet.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--include/net/xfrm.h2
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/xfrm6_policy.c3
-rw-r--r--net/xfrm/xfrm_policy.c15
4 files changed, 22 insertions, 0 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0f49f70dfd14..2a98d14b036f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -356,6 +356,8 @@ struct xfrm_dst_lookup_params {
xfrm_address_t *saddr;
xfrm_address_t *daddr;
u32 mark;
+ __u8 ipproto;
+ union flowi_uli uli;
};
struct net_device;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index ac1a28ef0c56..7e1c2faed1ff 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -30,6 +30,8 @@ static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4,
fl4->flowi4_mark = params->mark;
if (params->saddr)
fl4->saddr = params->saddr->a4;
+ fl4->flowi4_proto = params->ipproto;
+ fl4->uli = params->uli;
rt = __ip_route_output_key(params->net, fl4);
if (!IS_ERR(rt))
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index fc3f5eec6898..1f19b6f14484 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -37,6 +37,9 @@ static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *p
if (params->saddr)
memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr));
+ fl6.flowi4_proto = params->ipproto;
+ fl6.uli = params->uli;
+
dst = ip6_route_output(params->net, NULL, &fl6);
err = dst->error;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1025b5b3a1dd..d30a22cd5c62 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -312,6 +312,21 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
params.tos = tos;
params.oif = oif;
params.mark = mark;
+ params.ipproto = x->id.proto;
+ if (x->encap) {
+ switch (x->encap->encap_type) {
+ case UDP_ENCAP_ESPINUDP:
+ params.ipproto = IPPROTO_UDP;
+ params.uli.ports.sport = x->encap->encap_sport;
+ params.uli.ports.dport = x->encap->encap_dport;
+ break;
+ case TCP_ENCAP_ESPINTCP:
+ params.ipproto = IPPROTO_TCP;
+ params.uli.ports.sport = x->encap->encap_sport;
+ params.uli.ports.dport = x->encap->encap_dport;
+ break;
+ }
+ }
dst = __xfrm_dst_lookup(family, &params);