From 0bc5399d7723d9ecab5f71c30dcaea4041366446 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 29 Sep 2017 13:54:21 +0200 Subject: src: add alternate syntax for ct saddr current syntax is: ct original saddr $address problem is that in inet, bridge etc. we lack context to figure out if this should fetch ipv6 or ipv4 from the conntrack structure. $address might not exist, rhs could e.g. be a set reference. One way to do this is to have users manually specifiy the dependeny: ct l3proto ipv4 ct original saddr $address Thats ugly, and, moreover, only needed for table families other than ip or ipv6. Pablo suggested to instead specify ip saddr, ip6 saddr: ct original ip saddr $address and let nft handle the dependency injection. This adds the required parts to the scanner and the grammar, next commit adds code to eval step to make use of this. Signed-off-by: Florian Westphal --- src/ct.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/ct.c') diff --git a/src/ct.c b/src/ct.c index b2faf627..f99fc7f8 100644 --- a/src/ct.c +++ b/src/ct.c @@ -335,7 +335,7 @@ static const struct expr_ops ct_expr_ops = { }; struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key, - int8_t direction) + int8_t direction, uint8_t nfproto) { const struct ct_template *tmpl = &ct_templates[key]; struct expr *expr; @@ -344,6 +344,7 @@ struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key, tmpl->byteorder, tmpl->len); expr->ct.key = key; expr->ct.direction = direction; + expr->ct.nfproto = nfproto; switch (key) { case NFT_CT_PROTOCOL: -- cgit v1.2.3 From 41097c80a27ab5857d29d9d831805095455c855a Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 29 Sep 2017 13:54:21 +0200 Subject: src: ct: store proto base of ct key, if any ct keys can match on network and tranasport header protocol elements, such as port numbers or ip addresses. Store this base type so a followup commit can store and kill dependencies, e.g. if bsae is network header we might be able to kill an earlier expression because the dependency is implicit. Signed-off-by: Florian Westphal --- src/ct.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/ct.c') diff --git a/src/ct.c b/src/ct.c index f99fc7f8..044a6a50 100644 --- a/src/ct.c +++ b/src/ct.c @@ -347,8 +347,21 @@ struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key, expr->ct.nfproto = nfproto; switch (key) { + case NFT_CT_SRC: + case NFT_CT_DST: + expr->ct.base = PROTO_BASE_NETWORK_HDR; + break; + case NFT_CT_PROTO_SRC: + case NFT_CT_PROTO_DST: + expr->ct.base = PROTO_BASE_TRANSPORT_HDR; + break; case NFT_CT_PROTOCOL: expr->flags = EXPR_F_PROTOCOL; + expr->ct.base = PROTO_BASE_NETWORK_HDR; + break; + case NFT_CT_L3PROTOCOL: + expr->flags = EXPR_F_PROTOCOL; + expr->ct.base = PROTO_BASE_LL_HDR; break; default: break; -- cgit v1.2.3 From 2b29ea5f3c3ed693fc0579016569a36cb3796703 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 29 Sep 2017 13:54:21 +0200 Subject: src: ct: add eval part to inject dependencies for ct saddr/daddr nft has enough context to determine if a dependeny is needed. add rule ip filter ct original ip6 saddr allows nft to generate an error due to conflicting bases (ip vs ip6). add rule inet filter ct original ip6 saddr allows nft to inject an ipv6 dependency expression. add rule inet filter ct original saddr will print an error and will suggest to add ip/ip6 keyword. Delinerize and print support will be added in followup patches. Signed-off-by: Florian Westphal --- src/ct.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/ct.c') diff --git a/src/ct.c b/src/ct.c index 044a6a50..6130aade 100644 --- a/src/ct.c +++ b/src/ct.c @@ -308,21 +308,21 @@ static void ct_expr_clone(struct expr *new, const struct expr *expr) static void ct_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr) { const struct expr *left = expr->left, *right = expr->right; - const struct proto_desc *base, *desc; + const struct proto_desc *base = NULL, *desc; + uint32_t nhproto; assert(expr->op == OP_EQ); - switch (left->ct.key) { - case NFT_CT_PROTOCOL: - base = ctx->protocol[PROTO_BASE_NETWORK_HDR].desc; - desc = proto_find_upper(base, mpz_get_uint32(right->value)); + nhproto = mpz_get_uint32(right->value); - proto_ctx_update(ctx, PROTO_BASE_TRANSPORT_HDR, - &expr->location, desc); - break; - default: - break; - } + base = ctx->protocol[left->ct.base].desc; + if (!base) + return; + desc = proto_find_upper(base, nhproto); + if (!desc) + return; + + proto_ctx_update(ctx, left->ct.base + 1, &expr->location, desc); } static const struct expr_ops ct_expr_ops = { @@ -374,10 +374,11 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr) { const struct proto_desc *desc; + desc = ctx->protocol[expr->ct.base].desc; + switch (expr->ct.key) { case NFT_CT_SRC: case NFT_CT_DST: - desc = ctx->protocol[PROTO_BASE_NETWORK_HDR].desc; if (desc == &proto_ip) expr->dtype = &ipaddr_type; else if (desc == &proto_ip6) @@ -387,7 +388,6 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr) break; case NFT_CT_PROTO_SRC: case NFT_CT_PROTO_DST: - desc = ctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc; if (desc == NULL) break; expr->dtype = &inet_service_type; -- cgit v1.2.3 From 377e22c1a9a50fda2064746399129b0e5d1d448f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 29 Sep 2017 13:54:21 +0200 Subject: src: ct: print nfproto name for some header fields this prints "original saddr|daddr $NFPROTO" to make output symmetric with the syntax that we now prefer on input side. Signed-off-by: Florian Westphal --- src/ct.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'src/ct.c') diff --git a/src/ct.c b/src/ct.c index 6130aade..58b873e7 100644 --- a/src/ct.c +++ b/src/ct.c @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -269,9 +271,11 @@ static const struct ct_template ct_templates[] = { BYTEORDER_HOST_ENDIAN, 32), }; -static void ct_print(enum nft_ct_keys key, int8_t dir, struct output_ctx *octx) +static void ct_print(enum nft_ct_keys key, int8_t dir, uint8_t nfproto, + struct output_ctx *octx) { const struct symbolic_constant *s; + const struct proto_desc *desc; nft_print(octx, "ct "); if (dir < 0) @@ -283,13 +287,25 @@ static void ct_print(enum nft_ct_keys key, int8_t dir, struct output_ctx *octx) break; } } + + switch (key) { + case NFT_CT_SRC: /* fallthrough */ + case NFT_CT_DST: + desc = proto_find_upper(&proto_inet, nfproto); + if (desc) + printf("%s ", desc->name); + break; + default: + break; + } + done: nft_print(octx, "%s", ct_templates[key].token); } static void ct_expr_print(const struct expr *expr, struct output_ctx *octx) { - ct_print(expr->ct.key, expr->ct.direction, octx); + ct_print(expr->ct.key, expr->ct.direction, expr->ct.nfproto, octx); } static bool ct_expr_cmp(const struct expr *e1, const struct expr *e2) @@ -379,10 +395,13 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr) switch (expr->ct.key) { case NFT_CT_SRC: case NFT_CT_DST: - if (desc == &proto_ip) + if (desc == &proto_ip) { expr->dtype = &ipaddr_type; - else if (desc == &proto_ip6) + expr->ct.nfproto = NFPROTO_IPV4; + } else if (desc == &proto_ip6) { expr->dtype = &ip6addr_type; + expr->ct.nfproto = NFPROTO_IPV6; + } expr->len = expr->dtype->size; break; @@ -399,7 +418,7 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr) static void ct_stmt_print(const struct stmt *stmt, struct output_ctx *octx) { - ct_print(stmt->ct.key, stmt->ct.direction, octx); + ct_print(stmt->ct.key, stmt->ct.direction, 0, octx); nft_print(octx, " set "); expr_print(stmt->ct.expr, octx); } -- cgit v1.2.3