netfilter: nft_fib: reverse path filter for policy-based routing on iif
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 31 Mar 2022 15:14:47 +0000 (17:14 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 11 Apr 2022 10:10:09 +0000 (12:10 +0200)
If policy-based routing using the iif selector is used, then the fib
expression fails to look up for the reverse path from the prerouting
hook because the input interface cannot be inferred. In order to support
this scenario, extend the fib expression to allow to use after the route
lookup, from the forward hook.

This patch also adds support for the input hook for usability reasons.
Since the prerouting hook cannot be used for the scenario described
above, users need two rules: one for the forward chain and another rule
for the input chain to check for the reverse path check for locally
targeted traffic.

Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/ipv4/netfilter/nft_fib_ipv4.c
net/ipv6/netfilter/nft_fib_ipv6.c
net/netfilter/nft_fib.c

index 4151eb1262ddcd8e751ee530383920825eaf862f..b75cac69bd7e6b95eafc2b07aab571b93a8321fc 100644 (file)
@@ -112,6 +112,10 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
                fl4.daddr = iph->daddr;
                fl4.saddr = get_saddr(iph->saddr);
        } else {
+               if (nft_hook(pkt) == NF_INET_FORWARD &&
+                   priv->flags & NFTA_FIB_F_IIF)
+                       fl4.flowi4_iif = nft_out(pkt)->ifindex;
+
                fl4.daddr = iph->saddr;
                fl4.saddr = get_saddr(iph->daddr);
        }
index b3f163b40c2b2fc3c3549c895e3fa05cc95efe8a..8970d0b4faeb422fbcf335d9b75fa932dd87bd85 100644 (file)
@@ -30,6 +30,10 @@ static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv,
                fl6->daddr = iph->daddr;
                fl6->saddr = iph->saddr;
        } else {
+               if (nft_hook(pkt) == NF_INET_FORWARD &&
+                   priv->flags & NFTA_FIB_F_IIF)
+                       fl6->flowi6_iif = nft_out(pkt)->ifindex;
+
                fl6->daddr = iph->saddr;
                fl6->saddr = iph->daddr;
        }
index f198f2d9ef90941211db0d23ea783495a48ec2f1..1f12d7ade606c89496de381ba43b01addedac2f9 100644 (file)
@@ -35,6 +35,10 @@ int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
        case NFT_FIB_RESULT_OIF:
        case NFT_FIB_RESULT_OIFNAME:
                hooks = (1 << NF_INET_PRE_ROUTING);
+               if (priv->flags & NFTA_FIB_F_IIF) {
+                       hooks |= (1 << NF_INET_LOCAL_IN) |
+                                (1 << NF_INET_FORWARD);
+               }
                break;
        case NFT_FIB_RESULT_ADDRTYPE:
                if (priv->flags & NFTA_FIB_F_IIF)