From 9f3cce668b72c9ec9d9e0a6071d132a8f35d7b70 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 27 Apr 2016 12:29:49 +0100 Subject: stmt: support generating stateful statements outside of rule context The flow statement contains a stateful per flow statement, which is not directly part of the rule. Allow generating these statements without adding them to the rule and mark the supported statements using a new flag STMT_F_STATEFUL. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- src/netlink_linearize.c | 80 ++++++++++++++++++++++++++++++------------------- src/statement.c | 12 ++++++-- 2 files changed, 60 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index e0c73c0f..fbf6e2c3 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -619,14 +619,9 @@ static void netlink_gen_expr(struct netlink_linearize_ctx *ctx, } } -static void netlink_gen_verdict_stmt(struct netlink_linearize_ctx *ctx, - const struct stmt *stmt) -{ - return netlink_gen_expr(ctx, stmt->expr, NFT_REG_VERDICT); -} - -static void netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx, - const struct stmt *stmt) +static struct nftnl_expr * +netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) { struct nftnl_expr *nle; @@ -639,7 +634,46 @@ static void netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx, nftnl_expr_set_u64(nle, NFTNL_EXPR_CTR_BYTES, stmt->counter.bytes); } - nftnl_rule_add_expr(ctx->nlr, nle); + + return nle; +} + +static struct nftnl_expr * +netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) +{ + struct nftnl_expr *nle; + + nle = alloc_nft_expr("limit"); + nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_RATE, stmt->limit.rate); + nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_UNIT, stmt->limit.unit); + nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_TYPE, stmt->limit.type); + if (stmt->limit.burst > 0) + nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_BURST, + stmt->limit.burst); + nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_FLAGS, stmt->limit.flags); + + return nle; +} + +static struct nftnl_expr * +netlink_gen_stmt_stateful(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) +{ + switch (stmt->ops->type) { + case STMT_COUNTER: + return netlink_gen_counter_stmt(ctx, stmt); + case STMT_LIMIT: + return netlink_gen_limit_stmt(ctx, stmt); + default: + BUG("unknown stateful statement type %s\n", stmt->ops->name); + } +} + +static void netlink_gen_verdict_stmt(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) +{ + return netlink_gen_expr(ctx, stmt->expr, NFT_REG_VERDICT); } static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx, @@ -722,23 +756,6 @@ static void netlink_gen_log_stmt(struct netlink_linearize_ctx *ctx, nftnl_rule_add_expr(ctx->nlr, nle); } -static void netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx, - const struct stmt *stmt) -{ - struct nftnl_expr *nle; - - nle = alloc_nft_expr("limit"); - nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_RATE, stmt->limit.rate); - nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_UNIT, stmt->limit.unit); - nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_TYPE, stmt->limit.type); - if (stmt->limit.burst > 0) - nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_BURST, - stmt->limit.burst); - nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_FLAGS, stmt->limit.flags); - - nftnl_rule_add_expr(ctx->nlr, nle); -} - static void netlink_gen_reject_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { @@ -1022,21 +1039,19 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { + struct nftnl_expr *nle; + switch (stmt->ops->type) { case STMT_EXPRESSION: return netlink_gen_expr(ctx, stmt->expr, NFT_REG_VERDICT); case STMT_VERDICT: return netlink_gen_verdict_stmt(ctx, stmt); - case STMT_COUNTER: - return netlink_gen_counter_stmt(ctx, stmt); case STMT_PAYLOAD: return netlink_gen_payload_stmt(ctx, stmt); case STMT_META: return netlink_gen_meta_stmt(ctx, stmt); case STMT_LOG: return netlink_gen_log_stmt(ctx, stmt); - case STMT_LIMIT: - return netlink_gen_limit_stmt(ctx, stmt); case STMT_REJECT: return netlink_gen_reject_stmt(ctx, stmt); case STMT_NAT: @@ -1055,6 +1070,11 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, return netlink_gen_set_stmt(ctx, stmt); case STMT_FWD: return netlink_gen_fwd_stmt(ctx, stmt); + case STMT_COUNTER: + case STMT_LIMIT: + nle = netlink_gen_stmt_stateful(ctx, stmt); + nftnl_rule_add_expr(ctx->nlr, nle); + break; default: BUG("unknown statement type %s\n", stmt->ops->name); } diff --git a/src/statement.c b/src/statement.c index 2a6f19f8..41498418 100644 --- a/src/statement.c +++ b/src/statement.c @@ -117,7 +117,11 @@ static const struct stmt_ops counter_stmt_ops = { struct stmt *counter_stmt_alloc(const struct location *loc) { - return stmt_alloc(loc, &counter_stmt_ops); + struct stmt *stmt; + + stmt = stmt_alloc(loc, &counter_stmt_ops); + stmt->flags |= STMT_F_STATEFUL; + return stmt; } static const char *syslog_level[LOG_DEBUG + 1] = { @@ -249,7 +253,11 @@ static const struct stmt_ops limit_stmt_ops = { struct stmt *limit_stmt_alloc(const struct location *loc) { - return stmt_alloc(loc, &limit_stmt_ops); + struct stmt *stmt; + + stmt = stmt_alloc(loc, &limit_stmt_ops); + stmt->flags |= STMT_F_STATEFUL; + return stmt; } static void queue_stmt_print(const struct stmt *stmt) -- cgit v1.2.3