summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2025-06-24 18:11:06 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2025-06-27 00:39:05 +0200
commitf4b646032acff4d743ad4f734aaca68e9264bdbb (patch)
tree9cd4d2172b7b61a7cc17c33b51a8a6d3e6baea34 /src
parent646acfaceb1f550c982c31ba6e60996b0bb012d7 (diff)
fib: allow to check if route exists in maps
f686a17eafa0 ("fib: Support existence check") adds EXPR_F_BOOLEAN as a workaround to infer from the rhs of the relational expression if the fib lookup wants to check for a specific output interface or, instead, simply check for existence. This, however, does not work with maps. The NFT_FIB_F_PRESENT flag can be used both with NFT_FIB_RESULT_OIF and NFT_FIB_RESULT_OFINAME, my understanding is that they serve the same purpose which is to check if a route exists, so they are redundant. Add a 'check' fib result to check for routes while still keeping the inference workaround for backward compatibility, but prefer the new syntax in the listing. Update man nft(8) and tests/py. Fixes: f686a17eafa0 ("fib: Support existence check") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/fib.c12
-rw-r--r--src/json.c2
-rw-r--r--src/parser_bison.y21
-rw-r--r--src/parser_json.c12
-rw-r--r--src/scanner.l4
5 files changed, 40 insertions, 11 deletions
diff --git a/src/fib.c b/src/fib.c
index 5a7c1170..e28c5224 100644
--- a/src/fib.c
+++ b/src/fib.c
@@ -53,8 +53,16 @@ const struct datatype fib_addr_type = {
.sym_tbl = &addrtype_tbl,
};
-const char *fib_result_str(enum nft_fib_result result)
+const char *fib_result_str(const struct expr *expr)
{
+ enum nft_fib_result result = expr->fib.result;
+ uint32_t flags = expr->fib.flags;
+
+ /* Exception: check if route exists. */
+ if (result == NFT_FIB_RESULT_OIF &&
+ flags & NFTA_FIB_F_PRESENT)
+ return "check";
+
if (result <= NFT_FIB_RESULT_MAX)
return fib_result[result];
@@ -87,7 +95,7 @@ static void fib_expr_print(const struct expr *expr, struct output_ctx *octx)
if (flags)
nft_print(octx, "0x%x", flags);
- nft_print(octx, " %s", fib_result_str(expr->fib.result));
+ nft_print(octx, " %s", fib_result_str(expr));
}
static bool fib_expr_cmp(const struct expr *e1, const struct expr *e2)
diff --git a/src/json.c b/src/json.c
index 5bd5daf3..f0430776 100644
--- a/src/json.c
+++ b/src/json.c
@@ -938,7 +938,7 @@ json_t *fib_expr_json(const struct expr *expr, struct output_ctx *octx)
unsigned int flags = expr->fib.flags & ~NFTA_FIB_F_PRESENT;
json_t *root;
- root = nft_json_pack("{s:s}", "result", fib_result_str(expr->fib.result));
+ root = nft_json_pack("{s:s}", "result", fib_result_str(expr));
if (flags) {
json_t *tmp = json_array();
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 9278b67a..e1afbbb6 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -284,6 +284,7 @@ int nft_lex(void *, void *, void *);
%token UNDEFINE "undefine"
%token FIB "fib"
+%token CHECK "check"
%token SOCKET "socket"
%token TRANSPARENT "transparent"
@@ -4360,30 +4361,38 @@ primary_expr : symbol_expr { $$ = $1; }
fib_expr : FIB fib_tuple fib_result close_scope_fib
{
- if (($2 & (NFTA_FIB_F_SADDR|NFTA_FIB_F_DADDR)) == 0) {
+ uint32_t flags = $2, result = $3;
+
+ if (result == __NFT_FIB_RESULT_MAX) {
+ result = NFT_FIB_RESULT_OIF;
+ flags |= NFTA_FIB_F_PRESENT;
+ }
+
+ if ((flags & (NFTA_FIB_F_SADDR|NFTA_FIB_F_DADDR)) == 0) {
erec_queue(error(&@2, "fib: need either saddr or daddr"), state->msgs);
YYERROR;
}
- if (($2 & (NFTA_FIB_F_SADDR|NFTA_FIB_F_DADDR)) ==
- (NFTA_FIB_F_SADDR|NFTA_FIB_F_DADDR)) {
+ if ((flags & (NFTA_FIB_F_SADDR|NFTA_FIB_F_DADDR)) ==
+ (NFTA_FIB_F_SADDR|NFTA_FIB_F_DADDR)) {
erec_queue(error(&@2, "fib: saddr and daddr are mutually exclusive"), state->msgs);
YYERROR;
}
- if (($2 & (NFTA_FIB_F_IIF|NFTA_FIB_F_OIF)) ==
- (NFTA_FIB_F_IIF|NFTA_FIB_F_OIF)) {
+ if ((flags & (NFTA_FIB_F_IIF|NFTA_FIB_F_OIF)) ==
+ (NFTA_FIB_F_IIF|NFTA_FIB_F_OIF)) {
erec_queue(error(&@2, "fib: iif and oif are mutually exclusive"), state->msgs);
YYERROR;
}
- $$ = fib_expr_alloc(&@$, $2, $3);
+ $$ = fib_expr_alloc(&@$, flags, result);
}
;
fib_result : OIF { $$ =NFT_FIB_RESULT_OIF; }
| OIFNAME { $$ =NFT_FIB_RESULT_OIFNAME; }
| TYPE close_scope_type { $$ =NFT_FIB_RESULT_ADDRTYPE; }
+ | CHECK { $$ = __NFT_FIB_RESULT_MAX; } /* actually, NFT_FIB_F_PRESENT. */
;
fib_flag : SADDR { $$ = NFTA_FIB_F_SADDR; }
diff --git a/src/parser_json.c b/src/parser_json.c
index 3195d529..ce944740 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1157,6 +1157,7 @@ static struct expr *json_parse_fib_expr(struct json_ctx *ctx,
[NFT_FIB_RESULT_OIF] = "oif",
[NFT_FIB_RESULT_OIFNAME] = "oifname",
[NFT_FIB_RESULT_ADDRTYPE] = "type",
+ [__NFT_FIB_RESULT_MAX] = "check", /* Actually, NFT_FIB_F_PRESENT. */
};
enum nft_fib_result resultval = NFT_FIB_RESULT_UNSPEC;
const char *result;
@@ -1172,12 +1173,19 @@ static struct expr *json_parse_fib_expr(struct json_ctx *ctx,
break;
}
}
- if (resultval == NFT_FIB_RESULT_UNSPEC) {
+ switch (resultval) {
+ case NFT_FIB_RESULT_UNSPEC:
json_error(ctx, "Invalid fib result '%s'.", result);
return NULL;
+ case __NFT_FIB_RESULT_MAX:
+ resultval = NFT_FIB_RESULT_OIF;
+ flagval = NFTA_FIB_F_PRESENT;
+ break;
+ default:
+ break;
}
- flagval = parse_flags_array(ctx, root, "flags", fib_flag_parse);
+ flagval |= parse_flags_array(ctx, root, "flags", fib_flag_parse);
if (flagval < 0)
return NULL;
diff --git a/src/scanner.l b/src/scanner.l
index 4787cc12..b69d8e81 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -795,6 +795,10 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"fib" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_FIB); return FIB; }
+<SCANSTATE_EXPR_FIB>{
+ "check" { return CHECK; }
+}
+
"osf" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_OSF); return OSF; }
"synproxy" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_SYNPROXY); return SYNPROXY; }