diff options
author | Phil Sutter <phil@nwl.cc> | 2018-03-17 10:39:27 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-03-17 13:23:45 +0100 |
commit | fde8ddfc31bbc4015e8a76b40cc7e27bcd7920ff (patch) | |
tree | 33c8e5ca8bdb473d772950359e57a326738c2e91 /src/netlink_linearize.c | |
parent | 48632359f4dea5ee2484debba498ba069229e6d0 (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/netlink_linearize.c')
-rw-r--r-- | src/netlink_linearize.c | 135 |
1 files changed, 36 insertions, 99 deletions
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: |