diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/evaluate.c | 22 | ||||
-rw-r--r-- | src/parser_bison.y | 24 | ||||
-rw-r--r-- | src/rt.c | 15 |
3 files changed, 46 insertions, 15 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index 8735bb76..ca9180b7 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -662,32 +662,28 @@ static int expr_evaluate_payload(struct eval_ctx *ctx, struct expr **exprp) return 0; } -static int expr_error_base(struct list_head *msgs, const struct expr *e) -{ - return expr_error(msgs, e, - "meta nfproto ipv4 or ipv6 must be specified " - "before %s expression", e->ops->name); -} - /* * RT expression: validate protocol dependencies. */ static int expr_evaluate_rt(struct eval_ctx *ctx, struct expr **expr) { - const struct proto_desc *base; + static const char emsg[] = "cannot determine ip protocol version, use \"ip nexthop\" or \"ip6 nexthop\" instead"; struct expr *rt = *expr; rt_expr_update_type(&ctx->pctx, rt); - base = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc; switch (rt->rt.key) { case NFT_RT_NEXTHOP4: - if (base != &proto_ip) - return expr_error_base(ctx->msgs, rt); + if (rt->dtype != &ipaddr_type) + return expr_error(ctx->msgs, rt, "%s", emsg); + if (ctx->pctx.family == NFPROTO_IPV6) + return expr_error(ctx->msgs, rt, "%s nexthop will not match", "ip"); break; case NFT_RT_NEXTHOP6: - if (base != &proto_ip6) - return expr_error_base(ctx->msgs, rt); + if (rt->dtype != &ip6addr_type) + return expr_error(ctx->msgs, rt, "%s", emsg); + if (ctx->pctx.family == NFPROTO_IPV4) + return expr_error(ctx->msgs, rt, "%s nexthop will not match", "ip6"); break; default: break; diff --git a/src/parser_bison.y b/src/parser_bison.y index 0a74a7a5..f996d9d9 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -665,7 +665,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type <expr> rt_expr %destructor { expr_free($$); } rt_expr -%type <val> rt_key +%type <val> rt_key_proto rt_key %type <expr> ct_expr %destructor { expr_free($$); } ct_expr @@ -3246,10 +3246,32 @@ hash_expr : JHASH expr MOD NUM SEED NUM offset_opt } ; +rt_key_proto : IP { $$ = NFPROTO_IPV4; } + | IP6 { $$ = NFPROTO_IPV6; } + ; + rt_expr : RT rt_key { $$ = rt_expr_alloc(&@$, $2, true); } + | RT rt_key_proto rt_key + { + enum nft_rt_keys rtk = $3; + + switch ($2) { + case NFPROTO_IPV4: + break; + case NFPROTO_IPV6: + if ($3 == NFT_RT_NEXTHOP4) + rtk = NFT_RT_NEXTHOP6; + break; + default: + YYERROR; + break; + } + + $$ = rt_expr_alloc(&@$, rtk, false); + } ; rt_key : CLASSID { $$ = NFT_RT_CLASSID; } @@ -82,7 +82,20 @@ static const struct rt_template rt_templates[] = { static void rt_expr_print(const struct expr *expr, struct output_ctx *octx) { - nft_print(octx, "rt %s", rt_templates[expr->rt.key].token); + const char *ip = ""; + + switch (expr->rt.key) { + case NFT_RT_NEXTHOP4: + ip = "ip "; + break; + case NFT_RT_NEXTHOP6: + ip = "ip6 "; + break; + default: + break; + } + + nft_print(octx, "rt %s%s", ip, rt_templates[expr->rt.key].token); } static bool rt_expr_cmp(const struct expr *e1, const struct expr *e2) |