diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-01-02 15:36:33 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-01-02 15:36:33 +0100 |
commit | c1f92755437ea4eee10950a196a5c749329ae5f6 (patch) | |
tree | 33c6f8fb7f262b274d494a91f3aa43c41dff5c9c /src/payload.c | |
parent | 75b096c094a5ee1d6ef443f16d6b55fa3dd1f197 (diff) |
src: add gre support
GRE has a number of fields that are conditional based on flags,
which requires custom dependency code similar to icmp and icmpv6.
Matching on optional fields is not supported at this stage.
Since this is a layer 3 tunnel protocol, an implicit dependency on
NFT_META_L4PROTO for IPPROTO_GRE is generated. To achieve this, this
patch adds new infrastructure to remove an outer dependency based on
the inner protocol from delinearize path.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/payload.c')
-rw-r--r-- | src/payload.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/payload.c b/src/payload.c index 71b29a09..ed76623c 100644 --- a/src/payload.c +++ b/src/payload.c @@ -487,6 +487,14 @@ payload_gen_special_dependency(struct eval_ctx *ctx, const struct expr *expr) break; } + /* this tunnel protocol does not encapsulate an inner + * link layer, use proto_netdev which relies on + * NFT_META_PROTOCOL for dependencies. + */ + if (expr->payload.inner_desc && + !(expr->payload.inner_desc->inner.flags & NFT_INNER_LL)) + desc = &proto_netdev; + desc_upper = &proto_ip6; if (expr->payload.desc == &proto_icmp || expr->payload.desc == &proto_igmp) @@ -1357,3 +1365,42 @@ bad_proto: return expr_error(ctx->msgs, expr, "incompatible icmp match: rule has %d, need %u", pctx->th_dep.icmp.type, type); } + +int payload_gen_inner_dependency(struct eval_ctx *ctx, const struct expr *expr, + struct stmt **res) +{ + struct proto_ctx *pctx = eval_proto_ctx(ctx); + const struct proto_hdr_template *tmpl; + const struct proto_desc *desc, *inner_desc; + struct expr *left, *right, *dep; + struct stmt *stmt = NULL; + int protocol; + + assert(expr->etype == EXPR_PAYLOAD); + + inner_desc = expr->payload.inner_desc; + desc = pctx->protocol[inner_desc->base - 1].desc; + if (desc == NULL) + desc = &proto_ip; + + tmpl = &inner_desc->templates[0]; + assert(tmpl); + + protocol = proto_find_num(desc, inner_desc); + if (protocol < 0) + return expr_error(ctx->msgs, expr, + "conflicting protocols specified: %s vs. %s", + desc->name, inner_desc->name); + + left = meta_expr_alloc(&expr->location, tmpl->meta_key); + + right = constant_expr_alloc(&expr->location, tmpl->dtype, + tmpl->dtype->byteorder, tmpl->len, + constant_data_ptr(protocol, tmpl->len)); + + dep = relational_expr_alloc(&expr->location, OP_EQ, left, right); + stmt = expr_stmt_alloc(&dep->location, dep); + + *res = stmt; + return 0; +} |