summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2015-09-29 18:21:54 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2015-09-30 17:32:10 +0200
commitb870b949470af0b1b578590b38efdd80048b539e (patch)
tree21fbd7c71aa63e3a95b0d4be80d56664b17b2cb7 /src/netlink_delinearize.c
parentde2ebd0e1d43361ecd879170b40bac76a503aa65 (diff)
src: add dup statement support
This allows you to clone packets to destination address, eg. ... dup to 172.20.0.2 ... dup to 172.20.0.2 device eth1 ... dup to ip saddr map { 192.168.0.2 : 172.20.0.2, ... } device eth1 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r--src/netlink_delinearize.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 2360681d..09f5932a 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -749,6 +749,52 @@ static void netlink_parse_redir(struct netlink_parse_ctx *ctx,
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
+static void netlink_parse_dup(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ const struct nftnl_expr *nle)
+{
+ enum nft_registers reg1, reg2;
+ struct expr *addr, *dev;
+ struct stmt *stmt;
+
+ stmt = dup_stmt_alloc(loc);
+
+ reg1 = netlink_parse_register(nle, NFTNL_EXPR_DUP_SREG_ADDR);
+ if (reg1) {
+ addr = netlink_get_register(ctx, loc, reg1);
+ if (addr == NULL)
+ return netlink_error(ctx, loc,
+ "DUP statement has no destination expression");
+
+ switch (ctx->table->handle.family) {
+ case NFPROTO_IPV4:
+ expr_set_type(addr, &ipaddr_type, BYTEORDER_BIG_ENDIAN);
+ break;
+ case NFPROTO_IPV6:
+ expr_set_type(addr, &ip6addr_type,
+ BYTEORDER_BIG_ENDIAN);
+ break;
+ }
+ stmt->dup.to = addr;
+ }
+
+ reg2 = netlink_parse_register(nle, NFTNL_EXPR_DUP_SREG_DEV);
+ if (reg2) {
+ dev = netlink_get_register(ctx, loc, reg2);
+ if (dev == NULL)
+ return netlink_error(ctx, loc,
+ "DUP statement has no output expression");
+
+ expr_set_type(dev, &ifindex_type, BYTEORDER_HOST_ENDIAN);
+ if (stmt->dup.to == NULL)
+ stmt->dup.to = dev;
+ else
+ stmt->dup.dev = dev;
+ }
+
+ list_add_tail(&stmt->list, &ctx->rule->stmts);
+}
+
static void netlink_parse_queue(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
@@ -837,6 +883,7 @@ static const struct {
{ .name = "nat", .parse = netlink_parse_nat },
{ .name = "masq", .parse = netlink_parse_masq },
{ .name = "redir", .parse = netlink_parse_redir },
+ { .name = "dup", .parse = netlink_parse_dup },
{ .name = "queue", .parse = netlink_parse_queue },
{ .name = "dynset", .parse = netlink_parse_dynset },
};
@@ -1460,6 +1507,12 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r
case STMT_SET:
expr_postprocess(&rctx, &stmt->set.key);
break;
+ case STMT_DUP:
+ if (stmt->dup.to != NULL)
+ expr_postprocess(&rctx, &stmt->dup.to);
+ if (stmt->dup.dev != NULL)
+ expr_postprocess(&rctx, &stmt->dup.dev);
+ break;
default:
break;
}