]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
stmt: support generating stateful statements outside of rule context
authorPatrick McHardy <kaber@trash.net>
Wed, 27 Apr 2016 11:29:49 +0000 (12:29 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 13 May 2016 17:30:29 +0000 (19:30 +0200)
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 <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/statement.h
src/netlink_linearize.c
src/statement.c

index e7872b0bd2cda494d5409e413362af7a7c42dc05..a6a86f949a46f44e2a8140fb025c07ccd76c585a 100644 (file)
@@ -197,6 +197,7 @@ struct stmt_ops {
 
 enum stmt_flags {
        STMT_F_TERMINAL         = 0x1,
+       STMT_F_STATEFUL         = 0x2,
 };
 
 /**
index e0c73c0f01dfecca8193a646e3f7779660f60e4f..fbf6e2c33befcd974bd28dcd187b9a529c889fb7 100644 (file)
@@ -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);
        }
index 2a6f19f8deec64ffcb64c264b0cc6ea47e40c5aa..414984188fee7149d72e8836b826826d4c2d8d32 100644 (file)
@@ -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)