From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [iptables-nftables RFC v3 PATCH 14/16] xtables: Support pure nft expressions for DNAT extension
Date: Fri, 9 Aug 2013 23:56:11 +0200 [thread overview]
Message-ID: <20130809215611.GC7102@localhost> (raw)
In-Reply-To: <1376055090-26551-15-git-send-email-tomasz.bursztyka@linux.intel.com>
On Fri, Aug 09, 2013 at 04:31:28PM +0300, Tomasz Bursztyka wrote:
> Add the support for DNAT xtables extensions to be expressed directly into
> pure nft expression and not more via the compatible expression "target".
> Provide also the function to register the different pattern of such
> extension when expressed purely in nft so it can be parsed back, and the
> memory blob can be recreated. Given callback from the core will then
> feed the command structure relevantly.
>
> Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
> ---
> extensions/libipt_DNAT.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 221 insertions(+)
>
> diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
> index ff18799..f6f0769 100644
> --- a/extensions/libipt_DNAT.c
> +++ b/extensions/libipt_DNAT.c
> @@ -7,6 +7,7 @@
> #include <limits.h> /* INT_MAX in ip_tables.h */
> #include <linux/netfilter_ipv4/ip_tables.h>
> #include <linux/netfilter/nf_nat.h>
> +#include <linux/netfilter/nf_tables.h>
>
> enum {
> O_TO_DEST = 0,
> @@ -242,6 +243,224 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target)
> }
> }
>
> +static struct nft_rule_expr *
> +add_nat_data(struct nft_rule *rule, int reg, uint32_t data)
> +{
> + struct nft_rule_expr *expr;
> +
> + expr = nft_rule_expr_alloc("immediate");
> + if (expr == NULL)
> + return NULL;
> +
> + nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, reg);
> + nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DATA, data);
> +
> + nft_rule_add_expr(rule, expr);
> +
> + return expr;
> +}
> +
> +static int add_nat_expr(struct nft_rule *rule,
> + const struct nf_nat_ipv4_range *r)
> +{
> + struct nft_rule_expr *nat_expr;
> + int registers = 1;
> +
> + nat_expr = nft_rule_expr_alloc("nat");
> + if (nat_expr == NULL)
> + return -1;
> +
> + nft_rule_expr_set_u32(nat_expr, NFT_EXPR_NAT_TYPE, NFT_NAT_DNAT);
> + nft_rule_expr_set_u32(nat_expr, NFT_EXPR_NAT_FAMILY, AF_INET);
> +
> + if (r->flags & NF_NAT_RANGE_MAP_IPS) {
> + nft_rule_expr_set_u32(nat_expr, NFT_EXPR_NAT_REG_ADDR_MIN,
> + registers);
> + if (add_nat_data(rule, registers, r->min_ip) == NULL)
> + goto error;
> + registers++;
> +
> + if (r->max_ip != r->min_ip) {
> + nft_rule_expr_set_u32(nat_expr,
> + NFT_EXPR_NAT_REG_ADDR_MAX,
> + registers);
> + if (add_nat_data(rule, registers, r->max_ip) == NULL)
> + goto error;
> + registers++;
> + }
> + }
> +
> + if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
> + nft_rule_expr_set_u32(nat_expr, NFT_EXPR_NAT_REG_PROTO_MIN,
> + registers);
> + if (add_nat_data(rule, registers,
> + ntohs(r->min.tcp.port)) == NULL)
> + goto error;
> + registers++;
> +
> + if (r->max.tcp.port != r->min.tcp.port) {
> + nft_rule_expr_set_u32(nat_expr,
> + NFT_EXPR_NAT_REG_PROTO_MAX,
> + registers);
> + if (add_nat_data(rule, registers,
> + ntohs(r->max.tcp.port)) == NULL)
> + goto error;
> + }
> + }
> +
> + nft_rule_add_expr(rule, nat_expr);
> +
> + return 0;
> +
> +error:
> + nft_rule_expr_free(nat_expr);
> + return -1;
> +}
> +
> +static int DNAT_to_nft(struct nft_rule *rule, struct xt_entry_target *target)
> +{
> + const struct ipt_natinfo *info = (const void *)target;
> + int i;
> +
> + for (i = 0; i < info->mr.rangesize; i++) {
> + if (add_nat_expr(rule, &info->mr.range[i]) < 0)
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static inline void get_nat_port(struct nft_rule_expr *expr, uint16_t *data)
> +{
> + uint32_t value;
> +
> + value = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_DATA);
> + *data = htons((uint16_t) value);
> +}
> +
> +static int DNAT_parse_nft(struct nft_trans_rule_context *rule_ctx,
> + struct nft_trans_instruction_context *first,
> + struct nft_trans_instruction_context *last,
> + nft_trans_parse_callback_f user_cb,
> + void *user_data)
> +{
> + struct nft_rule_expr *e_nat, *e;
> + struct nf_nat_ipv4_range range;
> + struct ipt_natinfo *info;
> + uint32_t type, reg;
> +
> + if (user_cb == NULL)
> + return -1;
> +
> + e_nat = nft_trans_instruction_context_get_expr(last);
> +
> + if (!nft_rule_expr_is_set(e_nat, NFT_EXPR_NAT_TYPE))
> + return -1;
> +
> + type = nft_rule_expr_get_u32(e_nat, NFT_EXPR_NAT_TYPE);
> + if (type != NFT_NAT_DNAT)
> + return -1;
> +
> + if (nft_rule_expr_is_set(e_nat, NFT_EXPR_NAT_REG_ADDR_MIN)) {
> + range.flags |= NF_NAT_RANGE_MAP_IPS;
> +
> + reg = nft_rule_expr_get_u32(e_nat, NFT_EXPR_NAT_REG_ADDR_MIN);
> + e = nft_trans_instruction_context_get_register(last, reg);
> + range.min_ip = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_DATA);
> +
> + if (nft_rule_expr_is_set(e_nat, NFT_EXPR_NAT_REG_ADDR_MAX)) {
> + reg = nft_rule_expr_get_u32(e_nat,
> + NFT_EXPR_NAT_REG_ADDR_MAX);
> + e = nft_trans_instruction_context_get_register(last, reg);
> + range.max_ip = nft_rule_expr_get_u32(e,
> + NFT_EXPR_IMM_DATA);
> + } else
> + range.max_ip = range.min_ip;
> + }
> +
> + if (nft_rule_expr_is_set(e_nat, NFT_EXPR_NAT_REG_PROTO_MIN)) {
> + range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
> +
> + reg = nft_rule_expr_get_u32(e_nat, NFT_EXPR_NAT_REG_PROTO_MIN);
> + e = nft_trans_instruction_context_get_register(last, reg);
> + get_nat_port(e, &range.min.tcp.port);
> +
> + if (nft_rule_expr_is_set(e_nat, NFT_EXPR_NAT_REG_PROTO_MAX)) {
> + reg = nft_rule_expr_get_u32(e_nat,
> + NFT_EXPR_NAT_REG_PROTO_MAX);
> + e = nft_trans_instruction_context_get_register(last, reg);
> + get_nat_port(e, &range.max.tcp.port);
> + } else
> + range.max.tcp.port = range.min.tcp.port;
> + }
This approach results in a fairly large parsing function. Note that
we'll have similar functions in SNAT and DNAT both for ipv4 and ipv6.
We have to find a better way to avoid bloating the existing
extensions.
> +
> + info = calloc(1, sizeof(struct ipt_natinfo));
> + if (info == NULL)
> + return -1;
> +
> + info = append_range(NULL, &range);
> + if (user_cb("DNAT", &info->t, user_data) != 0) {
> + free(info);
> + return -1;
> + }
The current kernels only support nat rangesize of 1 element, so no
need for this append_range handling.
next prev parent reply other threads:[~2013-08-09 21:56 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 01/16] xtables: Add support for injecting xtables target into nft rule Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 02/16] xtables: add support for injecting xtables matches " Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 03/16] nft: Add nft expressions translation engine as a library Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 04/16] nft: Integrate nft translator engine in current core Tomasz Bursztyka
2013-08-09 21:24 ` Pablo Neira Ayuso
2013-08-12 7:15 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 05/16] nft: Manage xtables target parsing through translation tree Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 06/16] nft: Manage xtables matches through nft " Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 07/16] nft: Add support for xtables extensions callback to change cs Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 08/16] xtables: Add support for registering nft translation function for target Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 09/16] xtables: Add support for registering nft translation function for match Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 10/16] nft: Register all relevant xtables extensions into translation tree Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 11/16] nft: Refactor firewall printing so it reuses already parsed cs struct Tomasz Bursztyka
2013-08-09 21:51 ` Pablo Neira Ayuso
2013-08-12 7:54 ` Tomasz Bursztyka
2013-08-12 9:30 ` Pablo Neira Ayuso
2013-08-12 10:54 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 12/16] nft: Refactor rule deletion so it compares both cs structure Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 13/16] xtables: nft: Complete refactoring on how rules are saved Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 14/16] xtables: Support pure nft expressions for DNAT extension Tomasz Bursztyka
2013-08-09 21:56 ` Pablo Neira Ayuso [this message]
2013-08-12 7:42 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 15/16] nft: Add a function to reset the counters of an existing rule Tomasz Bursztyka
2013-08-09 22:00 ` Pablo Neira Ayuso
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 16/16] xtables: Support -Z options for a given rule number Tomasz Bursztyka
2013-08-09 22:02 ` Pablo Neira Ayuso
2013-08-12 7:45 ` Tomasz Bursztyka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130809215611.GC7102@localhost \
--to=pablo@netfilter.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=tomasz.bursztyka@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).