summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/expression.h2
-rw-r--r--include/linux/netfilter/nf_tables.h1
-rw-r--r--src/evaluate.c14
-rw-r--r--src/expression.c4
-rw-r--r--src/fib.c5
-rw-r--r--tests/py/inet/fib.t3
-rw-r--r--tests/py/inet/fib.t.payload10
7 files changed, 37 insertions, 2 deletions
diff --git a/include/expression.h b/include/expression.h
index 423eae71..94573de0 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -171,12 +171,14 @@ struct expr_ops {
* @EXPR_F_SINGLETON: singleton (implies primary and constant)
* @EXPR_F_PROTOCOL: expressions describes upper layer protocol
* @EXPR_F_INTERVAL_END: set member ends an open interval
+ * @EXPR_F_BOOLEAN: expression is boolean (set by relational expr on LHS)
*/
enum expr_flags {
EXPR_F_CONSTANT = 0x1,
EXPR_F_SINGLETON = 0x2,
EXPR_F_PROTOCOL = 0x4,
EXPR_F_INTERVAL_END = 0x8,
+ EXPR_F_BOOLEAN = 0x10,
};
#include <payload.h>
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 4f7d7568..a9280a65 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -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 */
};
#define NFT_OBJECT_UNSPEC 0
diff --git a/src/evaluate.c b/src/evaluate.c
index 7c039cba..7ddbb658 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1658,6 +1658,17 @@ range:
return 0;
}
+static int expr_evaluate_fib(struct eval_ctx *ctx, struct expr **exprp)
+{
+ struct expr *expr = *exprp;
+
+ if (expr->flags & EXPR_F_BOOLEAN) {
+ expr->fib.flags |= NFTA_FIB_F_PRESENT;
+ expr->dtype = &boolean_type;
+ }
+ return expr_evaluate_primary(ctx, exprp);
+}
+
static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
{
#ifdef DEBUG
@@ -1680,8 +1691,9 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
return expr_evaluate_exthdr(ctx, expr);
case EXPR_VERDICT:
case EXPR_META:
- case EXPR_FIB:
return expr_evaluate_primary(ctx, expr);
+ case EXPR_FIB:
+ return expr_evaluate_fib(ctx, expr);
case EXPR_PAYLOAD:
return expr_evaluate_payload(ctx, expr);
case EXPR_RT:
diff --git a/src/expression.c b/src/expression.c
index da94b79f..a6065524 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -592,6 +592,10 @@ struct expr *relational_expr_alloc(const struct location *loc, enum ops op,
expr->left = left;
expr->op = op;
expr->right = right;
+
+ if (right->dtype == &boolean_type)
+ left->flags |= EXPR_F_BOOLEAN;
+
return expr;
}
diff --git a/src/fib.c b/src/fib.c
index c65677c8..28ef4b50 100644
--- a/src/fib.c
+++ b/src/fib.c
@@ -73,7 +73,7 @@ static void __fib_expr_print_f(unsigned int *flags, unsigned int f, const char *
static void fib_expr_print(const struct expr *expr)
{
- unsigned int flags = expr->fib.flags;
+ unsigned int flags = expr->fib.flags & ~NFTA_FIB_F_PRESENT;
printf("fib ");
__fib_expr_print_f(&flags, NFTA_FIB_F_SADDR, "saddr");
@@ -130,6 +130,9 @@ struct expr *fib_expr_alloc(const struct location *loc,
BUG("Unknown result %d\n", result);
}
+ if (flags & NFTA_FIB_F_PRESENT)
+ type = &boolean_type;
+
expr = expr_alloc(loc, &fib_expr_ops, type,
BYTEORDER_HOST_ENDIAN, len);
diff --git a/tests/py/inet/fib.t b/tests/py/inet/fib.t
index 9ee282ab..dbe45d95 100644
--- a/tests/py/inet/fib.t
+++ b/tests/py/inet/fib.t
@@ -12,3 +12,6 @@ fib saddr . iif oifname "lo";ok
fib daddr . iif type local;ok
fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept };ok
fib daddr . oif type local;fail
+
+fib daddr oif exists;ok
+fib daddr oif missing;ok
diff --git a/tests/py/inet/fib.t.payload b/tests/py/inet/fib.t.payload
index f5258165..1d4c3d94 100644
--- a/tests/py/inet/fib.t.payload
+++ b/tests/py/inet/fib.t.payload
@@ -20,3 +20,13 @@ __map%d test-ip 0
ip test-ip prerouting
[ fib daddr . iif type => reg 1 ]
[ lookup reg 1 set __map%d dreg 0 ]
+
+# fib daddr oif exists
+ip test-ip prerouting
+ [ fib daddr oif present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# fib daddr oif missing
+ip test-ip prerouting
+ [ fib daddr oif present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]