summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2016-04-27 12:29:50 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2016-05-13 19:30:29 +0200
commit3ed5e31f4a323d7f054b6120d05134195dc681f0 (patch)
tree5daa5afd681e9b3dbada6405659cd11cefc19554 /src/netlink_delinearize.c
parent9f3cce668b72c9ec9d9e0a6071d132a8f35d7b70 (diff)
src: add flow statement
The flow statement allows to instantiate per flow statements for user defined flows. This can so far be used for per flow accounting or limiting, similar to what the iptables hashlimit provides. Flows can be aged using the timeout option. Examples: # nft filter input flow ip saddr . tcp dport limit rate 10/second # nft filter input flow table acct iif . ip saddr timeout 60s counter Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r--src/netlink_delinearize.c49
1 files changed, 44 insertions, 5 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 1767098d..de5d66c0 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -35,6 +35,9 @@ struct netlink_parse_ctx {
struct expr *registers[1 + NFT_REG32_15 - NFT_REG32_00 + 1];
};
+static int netlink_parse_expr(const struct nftnl_expr *nle,
+ struct netlink_parse_ctx *ctx);
+
static void __fmtstring(3, 4) netlink_error(struct netlink_parse_ctx *ctx,
const struct location *loc,
const char *fmt, ...)
@@ -910,8 +913,9 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
{
+ const struct nftnl_expr *dnle;
struct expr *expr;
- struct stmt *stmt;
+ struct stmt *stmt, *dstmt;
struct set *set;
enum nft_registers sreg;
const char *name;
@@ -938,10 +942,28 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
expr = set_elem_expr_alloc(&expr->location, expr);
expr->timeout = nftnl_expr_get_u64(nle, NFTNL_EXPR_DYNSET_TIMEOUT);
- stmt = set_stmt_alloc(loc);
- stmt->set.set = set_ref_expr_alloc(loc, set);
- stmt->set.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP);
- stmt->set.key = expr;
+ dstmt = NULL;
+ dnle = nftnl_expr_get(nle, NFTNL_EXPR_DYNSET_EXPR, NULL);
+ if (dnle != NULL) {
+ if (netlink_parse_expr(dnle, ctx) < 0)
+ return;
+ if (ctx->stmt == NULL)
+ return netlink_error(ctx, loc,
+ "Could not parse dynset stmt");
+ dstmt = ctx->stmt;
+ }
+
+ if (dstmt != NULL) {
+ stmt = flow_stmt_alloc(loc);
+ stmt->flow.set = set_ref_expr_alloc(loc, set);
+ stmt->flow.key = expr;
+ stmt->flow.stmt = dstmt;
+ } else {
+ stmt = set_stmt_alloc(loc);
+ stmt->set.set = set_ref_expr_alloc(loc, set);
+ stmt->set.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP);
+ stmt->set.key = expr;
+ }
ctx->stmt = stmt;
}
@@ -1011,6 +1033,20 @@ static int netlink_parse_rule_expr(struct nftnl_expr *nle, void *arg)
return 0;
}
+struct stmt *netlink_parse_set_expr(const struct set *set,
+ const struct nftnl_expr *nle)
+{
+ struct netlink_parse_ctx ctx, *pctx = &ctx;
+
+ pctx->rule = rule_alloc(&netlink_location, &set->handle);
+ pctx->table = table_lookup(&set->handle);
+ assert(pctx->table != NULL);
+
+ if (netlink_parse_expr(nle, pctx) < 0)
+ return NULL;
+ return pctx->stmt;
+}
+
struct rule_pp_ctx {
struct proto_ctx pctx;
struct payload_dep_ctx pdctx;
@@ -1717,6 +1753,9 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r
stmt->payload.expr->byteorder);
expr_postprocess(&rctx, &stmt->payload.val);
break;
+ case STMT_FLOW:
+ expr_postprocess(&rctx, &stmt->flow.key);
+ break;
case STMT_META:
if (stmt->meta.expr != NULL)
expr_postprocess(&rctx, &stmt->meta.expr);