netfilter: nft_fib: Support existence check
authorPhil Sutter <phil@nwl.cc>
Fri, 10 Mar 2017 17:08:02 +0000 (18:08 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 13 Mar 2017 12:45:36 +0000 (13:45 +0100)
Instead of the actual interface index or name, set destination register
to just 1 or 0 depending on whether the lookup succeeded or not if
NFTA_FIB_F_PRESENT was set in userspace.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nft_fib.h
include/uapi/linux/netfilter/nf_tables.h
net/ipv4/netfilter/nft_fib_ipv4.c
net/ipv6/netfilter/nft_fib_ipv6.c
net/netfilter/nft_fib.c

index 5ceb2205e4e3ed93461ed4a3956b227f99ac9494..381af9469e6ada01e4acffd4efc3ebc88e66a019 100644 (file)
@@ -32,6 +32,6 @@ void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
 void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
                   const struct nft_pktinfo *pkt);
 
-void nft_fib_store_result(void *reg, enum nft_fib_result r,
+void nft_fib_store_result(void *reg, const struct nft_fib *priv,
                          const struct nft_pktinfo *pkt, int index);
 #endif
index 34c8d08b687ac1ea04a738d692b4acd23de153e7..8f3842690d176bb6d847e4a157dfc404d0e6f0f1 100644 (file)
@@ -1257,6 +1257,7 @@ enum nft_fib_flags {
        NFTA_FIB_F_MARK         = 1 << 2,       /* use skb->mark */
        NFTA_FIB_F_IIF          = 1 << 3,       /* restrict to iif */
        NFTA_FIB_F_OIF          = 1 << 4,       /* restrict to oif */
+       NFTA_FIB_F_PRESENT      = 1 << 5,       /* check existence only */
 };
 
 enum nft_ct_helper_attributes {
index 2981291910dd2cac2d508fcde89083afc22affd4..f4e4462cb5bb1b877fac32d7718ead86e97e91f2 100644 (file)
@@ -90,7 +90,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
 
        if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
            nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
-               nft_fib_store_result(dest, priv->result, pkt,
+               nft_fib_store_result(dest, priv, pkt,
                                     nft_in(pkt)->ifindex);
                return;
        }
@@ -99,7 +99,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
        if (ipv4_is_zeronet(iph->saddr)) {
                if (ipv4_is_lbcast(iph->daddr) ||
                    ipv4_is_local_multicast(iph->daddr)) {
-                       nft_fib_store_result(dest, priv->result, pkt,
+                       nft_fib_store_result(dest, priv, pkt,
                                             get_ifindex(pkt->skb->dev));
                        return;
                }
index 765facf03d45c47b9913b1adcdaf59b6fe09383c..e8d88d82636b759c68f348455ec17b526408b926 100644 (file)
@@ -159,7 +159,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
 
        if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
            nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
-               nft_fib_store_result(dest, priv->result, pkt,
+               nft_fib_store_result(dest, priv, pkt,
                                     nft_in(pkt)->ifindex);
                return;
        }
index fd0b19303b0db89faa316f9c9e47ced69cbae3fd..21df8cccea6582e56d7bfbb6fba21f821b7c56d9 100644 (file)
@@ -24,7 +24,8 @@ const struct nla_policy nft_fib_policy[NFTA_FIB_MAX + 1] = {
 EXPORT_SYMBOL(nft_fib_policy);
 
 #define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
-                       NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)
+                       NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF | \
+                       NFTA_FIB_F_PRESENT)
 
 int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
                     const struct nft_data **data)
@@ -133,19 +134,22 @@ int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr)
 }
 EXPORT_SYMBOL_GPL(nft_fib_dump);
 
-void nft_fib_store_result(void *reg, enum nft_fib_result r,
+void nft_fib_store_result(void *reg, const struct nft_fib *priv,
                          const struct nft_pktinfo *pkt, int index)
 {
        struct net_device *dev;
        u32 *dreg = reg;
 
-       switch (r) {
+       switch (priv->result) {
        case NFT_FIB_RESULT_OIF:
-               *dreg = index;
+               *dreg = (priv->flags & NFTA_FIB_F_PRESENT) ? !!index : index;
                break;
        case NFT_FIB_RESULT_OIFNAME:
                dev = dev_get_by_index_rcu(nft_net(pkt), index);
-               strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
+               if (priv->flags & NFTA_FIB_F_PRESENT)
+                       *dreg = !!dev;
+               else
+                       strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
                break;
        default:
                WARN_ON_ONCE(1);