From fde8ddfc31bbc4015e8a76b40cc7e27bcd7920ff Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sat, 17 Mar 2018 10:39:27 +0100 Subject: 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 Signed-off-by: Pablo Neira Ayuso --- src/netlink_linearize.c | 135 +++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 99 deletions(-) (limited to 'src/netlink_linearize.c') 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: -- cgit v1.2.3