summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-03-17 10:39:27 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-03-17 13:23:45 +0100
commitfde8ddfc31bbc4015e8a76b40cc7e27bcd7920ff (patch)
tree33c8e5ca8bdb473d772950359e57a326738c2e91 /src
parent48632359f4dea5ee2484debba498ba069229e6d0 (diff)
Combine redir and masq statements into nat
All these statements are very similar, handling them with the same code is obvious. The only thing required here is a custom extension of enum nft_nat_types which is used in nat_stmt to distinguish between snat and dnat already. Though since enum nft_nat_types is part of kernel uAPI, create a local extended version containing the additional fields. Note that nat statement printing got a bit more complicated to get the number of spaces right for every possible combination of attributes. Note also that there wasn't a case for STMT_MASQ in rule_parse_postprocess(), which seems like a bug. Since STMT_MASQ became just a variant of STMT_NAT, postprocessing will take place for it now anyway. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c40
-rw-r--r--src/netlink_delinearize.c32
-rw-r--r--src/netlink_linearize.c135
-rw-r--r--src/parser_bison.y38
-rw-r--r--src/statement.c74
5 files changed, 79 insertions, 240 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 8de5e48d..6ae94b0f 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2465,42 +2465,6 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
return 0;
}
-static int stmt_evaluate_masq(struct eval_ctx *ctx, struct stmt *stmt)
-{
- int err;
-
- err = nat_evaluate_family(ctx, stmt);
- if (err < 0)
- return err;
-
- if (stmt->masq.proto != NULL) {
- err = nat_evaluate_transport(ctx, stmt, &stmt->masq.proto);
- if (err < 0)
- return err;
- }
-
- stmt->flags |= STMT_F_TERMINAL;
- return 0;
-}
-
-static int stmt_evaluate_redir(struct eval_ctx *ctx, struct stmt *stmt)
-{
- int err;
-
- err = nat_evaluate_family(ctx, stmt);
- if (err < 0)
- return err;
-
- if (stmt->redir.proto != NULL) {
- err = nat_evaluate_transport(ctx, stmt, &stmt->redir.proto);
- if (err < 0)
- return err;
- }
-
- stmt->flags |= STMT_F_TERMINAL;
- return 0;
-}
-
static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt)
{
int err;
@@ -2758,10 +2722,6 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
return stmt_evaluate_reject(ctx, stmt);
case STMT_NAT:
return stmt_evaluate_nat(ctx, stmt);
- case STMT_MASQ:
- return stmt_evaluate_masq(ctx, stmt);
- case STMT_REDIR:
- return stmt_evaluate_redir(ctx, stmt);
case STMT_QUEUE:
return stmt_evaluate_queue(ctx, stmt);
case STMT_DUP:
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index b20047f1..754a307e 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -861,8 +861,8 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
enum nft_registers reg1, reg2;
int family;
- stmt = nat_stmt_alloc(loc);
- stmt->nat.type = nftnl_expr_get_u32(nle, NFTNL_EXPR_NAT_TYPE);
+ stmt = nat_stmt_alloc(loc,
+ nftnl_expr_get_u32(nle, NFTNL_EXPR_NAT_TYPE));
family = nftnl_expr_get_u32(nle, NFTNL_EXPR_NAT_FAMILY);
@@ -951,8 +951,8 @@ static void netlink_parse_masq(struct netlink_parse_ctx *ctx,
if (nftnl_expr_is_set(nle, NFTNL_EXPR_MASQ_FLAGS))
flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_MASQ_FLAGS);
- stmt = masq_stmt_alloc(loc);
- stmt->masq.flags = flags;
+ stmt = nat_stmt_alloc(loc, NFT_NAT_MASQ);
+ stmt->nat.flags = flags;
reg1 = netlink_parse_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MIN);
if (reg1) {
@@ -963,7 +963,7 @@ static void netlink_parse_masq(struct netlink_parse_ctx *ctx,
goto out_err;
}
expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
- stmt->masq.proto = proto;
+ stmt->nat.proto = proto;
}
reg2 = netlink_parse_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MAX);
@@ -975,9 +975,9 @@ static void netlink_parse_masq(struct netlink_parse_ctx *ctx,
goto out_err;
}
expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
- if (stmt->masq.proto != NULL)
- proto = range_expr_alloc(loc, stmt->masq.proto, proto);
- stmt->masq.proto = proto;
+ if (stmt->nat.proto != NULL)
+ proto = range_expr_alloc(loc, stmt->nat.proto, proto);
+ stmt->nat.proto = proto;
}
ctx->stmt = stmt;
@@ -995,11 +995,11 @@ static void netlink_parse_redir(struct netlink_parse_ctx *ctx,
enum nft_registers reg1, reg2;
uint32_t flags;
- stmt = redir_stmt_alloc(loc);
+ stmt = nat_stmt_alloc(loc, NFT_NAT_REDIR);
if (nftnl_expr_is_set(nle, NFTNL_EXPR_REDIR_FLAGS)) {
flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_REDIR_FLAGS);
- stmt->redir.flags = flags;
+ stmt->nat.flags = flags;
}
reg1 = netlink_parse_register(nle, NFTNL_EXPR_REDIR_REG_PROTO_MIN);
@@ -1012,7 +1012,7 @@ static void netlink_parse_redir(struct netlink_parse_ctx *ctx,
}
expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
- stmt->redir.proto = proto;
+ stmt->nat.proto = proto;
}
reg2 = netlink_parse_register(nle, NFTNL_EXPR_REDIR_REG_PROTO_MAX);
@@ -1025,10 +1025,10 @@ static void netlink_parse_redir(struct netlink_parse_ctx *ctx,
}
expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
- if (stmt->redir.proto != NULL)
- proto = range_expr_alloc(loc, stmt->redir.proto,
+ if (stmt->nat.proto != NULL)
+ proto = range_expr_alloc(loc, stmt->nat.proto,
proto);
- stmt->redir.proto = proto;
+ stmt->nat.proto = proto;
}
ctx->stmt = stmt;
@@ -2366,10 +2366,6 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r
if (stmt->nat.proto != NULL)
expr_postprocess(&rctx, &stmt->nat.proto);
break;
- case STMT_REDIR:
- if (stmt->redir.proto != NULL)
- expr_postprocess(&rctx, &stmt->redir.proto);
- break;
case STMT_REJECT:
stmt_reject_postprocess(&rctx);
break;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 12d143b5..1c06fc07 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -946,15 +946,43 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
enum nft_registers pmin_reg, pmax_reg;
int registers = 0;
int family;
+ int nftnl_flag_attr;
+ int nftnl_reg_pmin, nftnl_reg_pmax;
- nle = alloc_nft_expr("nat");
- nftnl_expr_set_u32(nle, NFTNL_EXPR_NAT_TYPE, stmt->nat.type);
+ switch (stmt->nat.type) {
+ case NFT_NAT_SNAT:
+ case NFT_NAT_DNAT:
+ nle = alloc_nft_expr("nat");
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_NAT_TYPE, stmt->nat.type);
- family = nftnl_rule_get_u32(ctx->nlr, NFTNL_RULE_FAMILY);
- nftnl_expr_set_u32(nle, NFTNL_EXPR_NAT_FAMILY, family);
+ family = nftnl_rule_get_u32(ctx->nlr, NFTNL_RULE_FAMILY);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_NAT_FAMILY, family);
+
+ nftnl_flag_attr = NFTNL_EXPR_NAT_FLAGS;
+ nftnl_reg_pmin = NFTNL_EXPR_NAT_REG_PROTO_MIN;
+ nftnl_reg_pmax = NFTNL_EXPR_NAT_REG_PROTO_MAX;
+ break;
+ case NFT_NAT_MASQ:
+ nle = alloc_nft_expr("masq");
+
+ nftnl_flag_attr = NFTNL_EXPR_MASQ_FLAGS;
+ nftnl_reg_pmin = NFTNL_EXPR_MASQ_REG_PROTO_MIN;
+ nftnl_reg_pmax = NFTNL_EXPR_MASQ_REG_PROTO_MAX;
+ break;
+ case NFT_NAT_REDIR:
+ nle = alloc_nft_expr("redir");
+
+ nftnl_flag_attr = NFTNL_EXPR_REDIR_FLAGS;
+ nftnl_reg_pmin = NFTNL_EXPR_REDIR_REG_PROTO_MIN;
+ nftnl_reg_pmax = NFTNL_EXPR_REDIR_REG_PROTO_MAX;
+ break;
+ default:
+ BUG("unknown nat type %d\n", stmt->nat.type);
+ break;
+ }
if (stmt->nat.flags != 0)
- nftnl_expr_set_u32(nle, NFTNL_EXPR_NAT_FLAGS, stmt->nat.flags);
+ nftnl_expr_set_u32(nle, nftnl_flag_attr, stmt->nat.flags);
if (stmt->nat.addr) {
amin_reg = get_register(ctx, NULL);
@@ -988,98 +1016,11 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
netlink_gen_expr(ctx, stmt->nat.proto->left, pmin_reg);
netlink_gen_expr(ctx, stmt->nat.proto->right, pmax_reg);
- netlink_put_register(nle, NFTNL_EXPR_NAT_REG_PROTO_MIN,
- pmin_reg);
- netlink_put_register(nle, NFTNL_EXPR_NAT_REG_PROTO_MAX,
- pmax_reg);
+ netlink_put_register(nle, nftnl_reg_pmin, pmin_reg);
+ netlink_put_register(nle, nftnl_reg_pmax, pmax_reg);
} else {
netlink_gen_expr(ctx, stmt->nat.proto, pmin_reg);
- netlink_put_register(nle, NFTNL_EXPR_NAT_REG_PROTO_MIN,
- pmin_reg);
- }
- }
-
- while (registers > 0) {
- release_register(ctx, NULL);
- registers--;
- }
-
- nftnl_rule_add_expr(ctx->nlr, nle);
-}
-
-static void netlink_gen_masq_stmt(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
-{
- enum nft_registers pmin_reg, pmax_reg;
- struct nftnl_expr *nle;
- int registers = 0;
-
- nle = alloc_nft_expr("masq");
- if (stmt->masq.flags != 0)
- nftnl_expr_set_u32(nle, NFTNL_EXPR_MASQ_FLAGS,
- stmt->masq.flags);
- if (stmt->masq.proto) {
- pmin_reg = get_register(ctx, NULL);
- registers++;
-
- if (stmt->masq.proto->ops->type == EXPR_RANGE) {
- pmax_reg = get_register(ctx, NULL);
- registers++;
-
- netlink_gen_expr(ctx, stmt->masq.proto->left, pmin_reg);
- netlink_gen_expr(ctx, stmt->masq.proto->right, pmax_reg);
- netlink_put_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MIN, pmin_reg);
- netlink_put_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MAX, pmax_reg);
- } else {
- netlink_gen_expr(ctx, stmt->masq.proto, pmin_reg);
- netlink_put_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MIN, pmin_reg);
- }
- }
-
- while (registers > 0) {
- release_register(ctx, NULL);
- registers--;
- }
-
- nftnl_rule_add_expr(ctx->nlr, nle);
-}
-
-static void netlink_gen_redir_stmt(struct netlink_linearize_ctx *ctx,
- const struct stmt *stmt)
-{
- struct nftnl_expr *nle;
- enum nft_registers pmin_reg, pmax_reg;
- int registers = 0;
-
- nle = alloc_nft_expr("redir");
-
- if (stmt->redir.flags != 0)
- nftnl_expr_set_u32(nle, NFTNL_EXPR_REDIR_FLAGS,
- stmt->redir.flags);
-
- if (stmt->redir.proto) {
- pmin_reg = get_register(ctx, NULL);
- registers++;
-
- if (stmt->redir.proto->ops->type == EXPR_RANGE) {
- pmax_reg = get_register(ctx, NULL);
- registers++;
-
- netlink_gen_expr(ctx, stmt->redir.proto->left,
- pmin_reg);
- netlink_gen_expr(ctx, stmt->redir.proto->right,
- pmax_reg);
- netlink_put_register(nle,
- NFTNL_EXPR_REDIR_REG_PROTO_MIN,
- pmin_reg);
- netlink_put_register(nle,
- NFTNL_EXPR_REDIR_REG_PROTO_MAX,
- pmax_reg);
- } else {
- netlink_gen_expr(ctx, stmt->redir.proto, pmin_reg);
- netlink_put_register(nle,
- NFTNL_EXPR_REDIR_REG_PROTO_MIN,
- pmin_reg);
+ netlink_put_register(nle, nftnl_reg_pmin, pmin_reg);
}
}
@@ -1310,10 +1251,6 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
return netlink_gen_reject_stmt(ctx, stmt);
case STMT_NAT:
return netlink_gen_nat_stmt(ctx, stmt);
- case STMT_MASQ:
- return netlink_gen_masq_stmt(ctx, stmt);
- case STMT_REDIR:
- return netlink_gen_redir_stmt(ctx, stmt);
case STMT_DUP:
return netlink_gen_dup_stmt(ctx, stmt);
case STMT_QUEUE:
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 9c143832..f1617eea 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2417,16 +2417,8 @@ reject_opts : /* empty */
nat_stmt : nat_stmt_alloc nat_stmt_args
;
-nat_stmt_alloc : SNAT
- {
- $$ = nat_stmt_alloc(&@$);
- $$->nat.type = NFT_NAT_SNAT;
- }
- | DNAT
- {
- $$ = nat_stmt_alloc(&@$);
- $$->nat.type = NFT_NAT_DNAT;
- }
+nat_stmt_alloc : SNAT { $$ = nat_stmt_alloc(&@$, NFT_NAT_SNAT); }
+ | DNAT { $$ = nat_stmt_alloc(&@$, NFT_NAT_DNAT); }
;
primary_stmt_expr : symbol_expr { $$ = $1; }
@@ -2576,21 +2568,21 @@ masq_stmt : masq_stmt_alloc masq_stmt_args
| masq_stmt_alloc
;
-masq_stmt_alloc : MASQUERADE { $$ = masq_stmt_alloc(&@$); }
+masq_stmt_alloc : MASQUERADE { $$ = nat_stmt_alloc(&@$, NFT_NAT_MASQ); }
;
masq_stmt_args : TO COLON stmt_expr
{
- $<stmt>0->masq.proto = $3;
+ $<stmt>0->nat.proto = $3;
}
| TO COLON stmt_expr nf_nat_flags
{
- $<stmt>0->masq.proto = $3;
- $<stmt>0->masq.flags = $4;
+ $<stmt>0->nat.proto = $3;
+ $<stmt>0->nat.flags = $4;
}
| nf_nat_flags
{
- $<stmt>0->masq.flags = $1;
+ $<stmt>0->nat.flags = $1;
}
;
@@ -2598,30 +2590,30 @@ redir_stmt : redir_stmt_alloc redir_stmt_arg
| redir_stmt_alloc
;
-redir_stmt_alloc : REDIRECT { $$ = redir_stmt_alloc(&@$); }
+redir_stmt_alloc : REDIRECT { $$ = nat_stmt_alloc(&@$, NFT_NAT_REDIR); }
;
redir_stmt_arg : TO stmt_expr
{
- $<stmt>0->redir.proto = $2;
+ $<stmt>0->nat.proto = $2;
}
| TO COLON stmt_expr
{
- $<stmt>0->redir.proto = $3;
+ $<stmt>0->nat.proto = $3;
}
| nf_nat_flags
{
- $<stmt>0->redir.flags = $1;
+ $<stmt>0->nat.flags = $1;
}
| TO stmt_expr nf_nat_flags
{
- $<stmt>0->redir.proto = $2;
- $<stmt>0->redir.flags = $3;
+ $<stmt>0->nat.proto = $2;
+ $<stmt>0->nat.flags = $3;
}
| TO COLON stmt_expr nf_nat_flags
{
- $<stmt>0->redir.proto = $3;
- $<stmt>0->redir.flags = $4;
+ $<stmt>0->nat.proto = $3;
+ $<stmt>0->nat.flags = $4;
}
;
diff --git a/src/statement.c b/src/statement.c
index d495ec44..b8e0b036 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -499,10 +499,16 @@ static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
static const char * const nat_types[] = {
[NFT_NAT_SNAT] = "snat",
[NFT_NAT_DNAT] = "dnat",
+ [NFT_NAT_MASQ] = "masquerade",
+ [NFT_NAT_REDIR] = "redirect",
};
- nft_print(octx, "%s to ", nat_types[stmt->nat.type]);
+ nft_print(octx, "%s", nat_types[stmt->nat.type]);
+ if (stmt->nat.addr || stmt->nat.proto)
+ nft_print(octx, " to");
+
if (stmt->nat.addr) {
+ nft_print(octx, " ");
if (stmt->nat.proto) {
if (stmt->nat.addr->ops->type == EXPR_VALUE &&
stmt->nat.addr->dtype->type == TYPE_IP6ADDR) {
@@ -525,6 +531,8 @@ static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
}
if (stmt->nat.proto) {
+ if (!stmt->nat.addr)
+ nft_print(octx, " ");
nft_print(octx, ":");
expr_print(stmt->nat.proto, octx);
}
@@ -545,67 +553,13 @@ static const struct stmt_ops nat_stmt_ops = {
.destroy = nat_stmt_destroy,
};
-struct stmt *nat_stmt_alloc(const struct location *loc)
-{
- return stmt_alloc(loc, &nat_stmt_ops);
-}
-
-static void masq_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
-{
- nft_print(octx, "masquerade");
-
- if (stmt->masq.proto) {
- nft_print(octx, " to :");
- expr_print(stmt->masq.proto, octx);
- }
-
- print_nf_nat_flags(stmt->masq.flags, octx);
-}
-
-static void masq_stmt_destroy(struct stmt *stmt)
-{
- expr_free(stmt->masq.proto);
-}
-
-static const struct stmt_ops masq_stmt_ops = {
- .type = STMT_MASQ,
- .name = "masq",
- .print = masq_stmt_print,
- .destroy = masq_stmt_destroy,
-};
-
-struct stmt *masq_stmt_alloc(const struct location *loc)
-{
- return stmt_alloc(loc, &masq_stmt_ops);
-}
-
-static void redir_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
+struct stmt *nat_stmt_alloc(const struct location *loc,
+ enum nft_nat_etypes type)
{
- nft_print(octx, "redirect");
-
- if (stmt->redir.proto) {
- nft_print(octx, " to :");
- expr_print(stmt->redir.proto, octx);
- }
-
- print_nf_nat_flags(stmt->redir.flags, octx);
-}
+ struct stmt *stmt = stmt_alloc(loc, &nat_stmt_ops);
-static void redir_stmt_destroy(struct stmt *stmt)
-{
- expr_free(stmt->redir.proto);
-}
-
-static const struct stmt_ops redir_stmt_ops = {
- .type = STMT_REDIR,
- .name = "redir",
- .print = redir_stmt_print,
- .destroy = redir_stmt_destroy,
-};
-
-struct stmt *redir_stmt_alloc(const struct location *loc)
-{
- return stmt_alloc(loc, &redir_stmt_ops);
+ stmt->nat.type = type;
+ return stmt;
}
static const char * const set_stmt_op_names[] = {