summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/statement.h32
-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
6 files changed, 89 insertions, 262 deletions
diff --git a/include/statement.h b/include/statement.h
index bb4af9d3..fa0b5dfa 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -98,28 +98,22 @@ struct reject_stmt {
extern struct stmt *reject_stmt_alloc(const struct location *loc);
-struct nat_stmt {
- enum nft_nat_types type;
- struct expr *addr;
- struct expr *proto;
- uint32_t flags;
-};
-
-extern struct stmt *nat_stmt_alloc(const struct location *loc);
-
-struct masq_stmt {
- uint32_t flags;
- struct expr *proto;
+enum nft_nat_etypes {
+ __NFT_NAT_SNAT = NFT_NAT_SNAT,
+ __NFT_NAT_DNAT = NFT_NAT_DNAT,
+ NFT_NAT_MASQ,
+ NFT_NAT_REDIR,
};
-extern struct stmt *masq_stmt_alloc(const struct location *loc);
-
-struct redir_stmt {
+struct nat_stmt {
+ enum nft_nat_etypes type;
+ struct expr *addr;
struct expr *proto;
uint32_t flags;
};
-extern struct stmt *redir_stmt_alloc(const struct location *loc);
+extern struct stmt *nat_stmt_alloc(const struct location *loc,
+ enum nft_nat_etypes type);
struct queue_stmt {
struct expr *queue;
@@ -233,8 +227,6 @@ extern struct stmt *xt_stmt_alloc(const struct location *loc);
* @STMT_LOG: log statement
* @STMT_REJECT: REJECT statement
* @STMT_NAT: NAT statement
- * @STMT_MASQ: masquerade statement
- * @STMT_REDIR: redirect statement
* @STMT_QUEUE: QUEUE statement
* @STMT_CT: conntrack statement
* @STMT_SET: set statement
@@ -260,8 +252,6 @@ enum stmt_types {
STMT_LOG,
STMT_REJECT,
STMT_NAT,
- STMT_MASQ,
- STMT_REDIR,
STMT_QUEUE,
STMT_CT,
STMT_SET,
@@ -324,8 +314,6 @@ struct stmt {
struct limit_stmt limit;
struct reject_stmt reject;
struct nat_stmt nat;
- struct masq_stmt masq;
- struct redir_stmt redir;
struct queue_stmt queue;
struct quota_stmt quota;
struct ct_stmt ct;
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[] = {