diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2020-12-09 16:46:26 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2020-12-17 17:24:49 +0100 |
commit | 242965f452e64fef9faff6689df4b2c205823209 (patch) | |
tree | 2eaab70fe894e57984a9392fb6bc423ccab5ccbf /src/netlink_linearize.c | |
parent | ca7464bf51f3784b29e29a40cee2c73f1f0c4f7e (diff) |
src: add support for multi-statement in dynamic sets and maps
This patch allows for two statements for dynamic set updates, e.g.
nft rule x y add @y { ip daddr limit rate 1/second counter }
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_linearize.c')
-rw-r--r-- | src/netlink_linearize.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 05af8bb1..09d0c61c 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -1397,8 +1397,10 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { struct set *set = stmt->meter.set->set; - struct nftnl_expr *nle; enum nft_registers sreg_key; + struct nftnl_expr *nle; + int num_stmts = 0; + struct stmt *this; sreg_key = get_register(ctx, stmt->set.key->key); netlink_gen_expr(ctx, stmt->set.key->key, sreg_key); @@ -1414,9 +1416,20 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id); nft_rule_add_expr(ctx, nle, &stmt->location); - if (stmt->set.stmt) - nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, - netlink_gen_stmt_stateful(stmt->set.stmt), 0); + list_for_each_entry(this, &stmt->set.stmt_list, list) + num_stmts++; + + if (num_stmts == 1) { + list_for_each_entry(this, &stmt->set.stmt_list, list) { + nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, + netlink_gen_stmt_stateful(this), 0); + } + } else if (num_stmts > 1) { + list_for_each_entry(this, &stmt->set.stmt_list, list) { + nftnl_expr_add_expr(nle, NFTNL_EXPR_DYNSET_EXPRESSIONS, + netlink_gen_stmt_stateful(this)); + } + } } static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx, @@ -1426,6 +1439,8 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx, enum nft_registers sreg_data; enum nft_registers sreg_key; struct nftnl_expr *nle; + int num_stmts = 0; + struct stmt *this; sreg_key = get_register(ctx, stmt->map.key); netlink_gen_expr(ctx, stmt->map.key, sreg_key); @@ -1443,12 +1458,22 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx, nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_OP, stmt->map.op); nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, set->handle.set.name); nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id); + nft_rule_add_expr(ctx, nle, &stmt->location); - if (stmt->map.stmt) - nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, - netlink_gen_stmt_stateful(stmt->map.stmt), 0); + list_for_each_entry(this, &stmt->map.stmt_list, list) + num_stmts++; - nft_rule_add_expr(ctx, nle, &stmt->location); + if (num_stmts == 1) { + list_for_each_entry(this, &stmt->map.stmt_list, list) { + nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR, + netlink_gen_stmt_stateful(this), 0); + } + } else if (num_stmts > 1) { + list_for_each_entry(this, &stmt->map.stmt_list, list) { + nftnl_expr_add_expr(nle, NFTNL_EXPR_DYNSET_EXPRESSIONS, + netlink_gen_stmt_stateful(this)); + } + } } static void netlink_gen_meter_stmt(struct netlink_linearize_ctx *ctx, |