* [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer)
@ 2013-08-09 13:31 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
` (15 more replies)
0 siblings, 16 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Rebased patch set of my RFC, against latest trunk.
Still requires to be built with --enable-static due to patch 10 (and that's something to be fixed, see below)
@Pablo: could you spend some time reviewing it, please? Don't spend too much yet on the code (though I have tested it and it works very well),
but I would like your opinion on the idea it implements. Code could be then changed/adapted if necessary.
To sum up:
- Parsing of rule happen one time in only one place (nft_rule_expr_iter() is called only once for good), via an expression pattern matching mechanism.
- Centralized parsing strategy for both usual stuff (ips, ifs, verdicts...) and also all xtables extensions.
It recreates an iptables_command_structure. That's why there is a lot of refactoring (it removes a lot of duplicate expression list loops etc...)
- And of course transparent support on xtables extensions for both full nft based expressions list or when using xt compat layer in nftables.
(so it will require now to "translate" little by little all xtables extensions, but the result will be transparent to the user. It will just get rid of the old fashioned xtables memory blob
one after another. So at some point it will work without any xtables modules in kernel side. DNAT is provided as an example here).
- Same strategy woulde be used in futur xtables-arptables and xtables-ebtables.
That's why, all in all, code base does not grow much (only ~40+ lines added).
The only "drawback" is this patch 10. It's required to know before hand every xtables extensions's nft expressions patterns so it's necessary for
them to be "pre-loaded", that's why currently it only works with --enable-static. We could add a function in xtables to pre-load shared libs to support --enable-shared without --enable-static.
It's not perfect here, I really would lik to get your input on that.
Tomasz Bursztyka (16):
xtables: Add support for injecting xtables target into nft rule
xtables: add support for injecting xtables matches into nft rule
nft: Add nft expressions translation engine as a library
nft: Integrate nft translator engine in current core
nft: Manage xtables target parsing through translation tree
nft: Manage xtables matches through nft translation tree
nft: Add support for xtables extensions callback to change cs
xtables: Add support for registering nft translation function for
target
xtables: Add support for registering nft translation function for
match
nft: Register all relevant xtables extensions into translation tree
nft: Refactor firewall printing so it reuses already parsed cs struct
nft: Refactor rule deletion so it compares both cs structure
xtables: nft: Complete refactoring on how rules are saved
xtables: Support pure nft expressions for DNAT extension
nft: Add a function to reset the counters of an existing rule
xtables: Support -Z options for a given rule number
Makefile.am | 3 +
configure.ac | 8 +
extensions/GNUmakefile.in | 1 +
extensions/libipt_DNAT.c | 221 ++++++++++++++++
include/nft-translator.h | 81 ++++++
include/xtables.h | 13 +
iptables/Makefile.am | 3 +-
iptables/nft-ipv4.c | 138 ++++------
iptables/nft-ipv6.c | 94 +++----
iptables/nft-shared.c | 447 ++++++++++++++++++---------------
iptables/nft-shared.h | 36 ++-
iptables/nft-xt-ext.c | 178 +++++++++++++
iptables/nft-xt-ext.h | 14 ++
iptables/nft.c | 556 ++++++++++------------------------------
iptables/nft.h | 5 +-
iptables/xtables-events.c | 21 +-
iptables/xtables.c | 15 +-
libnfttrans/Makefile.am | 28 +++
libnfttrans/libnfttrans.pc | 11 +
libnfttrans/libnfttrans.pc.in | 11 +
libnfttrans/nft-translator.c | 571 ++++++++++++++++++++++++++++++++++++++++++
21 files changed, 1651 insertions(+), 804 deletions(-)
create mode 100644 include/nft-translator.h
create mode 100644 iptables/nft-xt-ext.c
create mode 100644 iptables/nft-xt-ext.h
create mode 100644 libnfttrans/Makefile.am
create mode 100644 libnfttrans/libnfttrans.pc
create mode 100644 libnfttrans/libnfttrans.pc.in
create mode 100644 libnfttrans/nft-translator.c
--
1.8.3.2
^ permalink raw reply [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 01/16] xtables: Add support for injecting xtables target into nft rule
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 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 02/16] xtables: add support for injecting xtables matches " Tomasz Bursztyka
` (14 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
This bring the support for xtables target extentions to be translated to
pure nft expression list in the given rule.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
configure.ac | 7 +++++++
extensions/GNUmakefile.in | 1 +
include/xtables.h | 5 +++++
iptables/nft.c | 20 ++++++++++++--------
4 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac
index 1c713e8..68f661c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -119,6 +119,13 @@ PKG_CHECK_MODULES([libnftables], [libnftables >= 1.0],
[nftables=1], [nftables=0])
AM_CONDITIONAL([HAVE_LIBNFTABLES], [test "$nftables" = 1])
+if test "$nftables" = 1; then
+ EXTENSION_NFT_LDFLAGS="${libmnl_LIBS} ${libnftables_LIBS}";
+else
+ EXTENSION_NFT_LDFLAGS="";
+fi;
+AC_SUBST(EXTENSION_NFT_LDFLAGS)
+
AM_PROG_LEX
AC_PROG_YACC
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index 14e7c57..da2f38b 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -16,6 +16,7 @@ CCLD = ${CC}
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
+@ENABLE_NFTABLES_TRUE@ LDFLAGS += @EXTENSION_NFT_LDFLAGS@
regular_CFLAGS = @regular_CFLAGS@
regular_CPPFLAGS = @regular_CPPFLAGS@
kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
diff --git a/include/xtables.h b/include/xtables.h
index d4a4395..4d8874c 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -18,6 +18,8 @@
#include <linux/netfilter.h>
#include <linux/netfilter/x_tables.h>
+#include <libnftables/rule.h>
+
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
#endif
@@ -346,6 +348,9 @@ struct xtables_target
void (*x6_fcheck)(struct xt_fcheck_call *);
const struct xt_option_entry *x6_options;
+ /* NFT related */
+ int (*to_nft)(struct nft_rule *, struct xt_entry_target *);
+
size_t udata_size;
/* Ignore these men behind the curtain: */
diff --git a/iptables/nft.c b/iptables/nft.c
index 28e71d8..68861a8 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -594,17 +594,21 @@ static int __add_target(struct nft_rule_expr *e, struct xt_entry_target *t)
return 0;
}
-static int add_target(struct nft_rule *r, struct xt_entry_target *t)
+static int add_target(struct nft_rule *r, struct xtables_target *target)
{
- struct nft_rule_expr *expr;
int ret;
- expr = nft_rule_expr_alloc("target");
- if (expr == NULL)
- return -ENOMEM;
+ if (target->to_nft == NULL) {
+ struct nft_rule_expr *expr;
- ret = __add_target(expr, t);
- nft_rule_add_expr(r, expr);
+ expr = nft_rule_expr_alloc("target");
+ if (expr == NULL)
+ return -ENOMEM;
+
+ ret = __add_target(expr, target->t);
+ nft_rule_add_expr(r, expr);
+ } else
+ ret = target->to_nft(r, target->t);
return ret;
}
@@ -713,7 +717,7 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
ret = add_verdict(r, NFT_RETURN);
else
- ret = add_target(r, cs->target->t);
+ ret = add_target(r, cs->target);
} else if (strlen(cs->jumpto) > 0) {
/* Not standard, then it's a go / jump to chain */
if (ip_flags & IPT_F_GOTO)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 02/16] xtables: add support for injecting xtables matches into nft rule
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 ` 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
` (13 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
This bring the support for xtables matches extentions to be translated to
pure nft expression list in the given rule.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
include/xtables.h | 3 +++
iptables/nft.c | 20 ++++++++++++--------
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/include/xtables.h b/include/xtables.h
index 4d8874c..5bd8a59 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -271,6 +271,9 @@ struct xtables_match
void (*x6_fcheck)(struct xt_fcheck_call *);
const struct xt_option_entry *x6_options;
+ /* NFT related */
+ int (*to_nft)(struct nft_rule *r, struct xt_entry_match *);
+
/* Size of per-extension instance extra "global" scratch space */
size_t udata_size;
diff --git a/iptables/nft.c b/iptables/nft.c
index 68861a8..d92e8bb 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -558,17 +558,21 @@ static int __add_match(struct nft_rule_expr *e, struct xt_entry_match *m)
return 0;
}
-static int add_match(struct nft_rule *r, struct xt_entry_match *m)
+static int add_match(struct nft_rule *r, struct xtables_match *match)
{
- struct nft_rule_expr *expr;
int ret;
- expr = nft_rule_expr_alloc("match");
- if (expr == NULL)
- return -ENOMEM;
+ if (match->to_nft == NULL) {
+ struct nft_rule_expr *expr;
- ret = __add_match(expr, m);
- nft_rule_add_expr(r, expr);
+ expr = nft_rule_expr_alloc("match");
+ if (expr == NULL)
+ return -ENOMEM;
+
+ ret = __add_match(expr, match->m);
+ nft_rule_add_expr(r, expr);
+ } else
+ ret = match->to_nft(r, match->m);
return ret;
}
@@ -697,7 +701,7 @@ nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
ip_flags = h->ops->add(r, cs);
for (matchp = cs->matches; matchp; matchp = matchp->next) {
- if (add_match(r, matchp->match->m) < 0)
+ if (add_match(r, matchp->match) < 0)
goto err;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 03/16] nft: Add nft expressions translation engine as a library
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 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 04/16] nft: Integrate nft translator engine in current core Tomasz Bursztyka
` (12 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
libnfttrans is a generic translation engine from nft expressions to
registered "complex instructions". It works on a simple tree based
pattern matching algorithm.
Idea is to be able to register any kind of expressions suit (or pattern)
linked to a parsing function representing the "complex instruction".
Then, being able to go through the whole expression list of a rule and
retrieving the original complex instructions suit.
This will fix at once the parsing of a rule, taking into account
current compatilbe layer for extentions but also their pure nft version.
As soon as an expression will implement its method to express itself as
pur nft expression the change will be totally transparent.
Once applied on xtables (iptables over nftables), this will allow to
retrieve the exact iptables_command_state structure for instance.
However, such engine is generic enough to be reused in any other tool,
like future arptables and ebtables compatible tool over nftables.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
Makefile.am | 3 +
configure.ac | 1 +
include/nft-translator.h | 81 ++++++
libnfttrans/Makefile.am | 28 +++
libnfttrans/libnfttrans.pc | 11 +
libnfttrans/libnfttrans.pc.in | 11 +
libnfttrans/nft-translator.c | 571 ++++++++++++++++++++++++++++++++++++++++++
7 files changed, 706 insertions(+)
create mode 100644 include/nft-translator.h
create mode 100644 libnfttrans/Makefile.am
create mode 100644 libnfttrans/libnfttrans.pc
create mode 100644 libnfttrans/libnfttrans.pc.in
create mode 100644 libnfttrans/nft-translator.c
diff --git a/Makefile.am b/Makefile.am
index c38d360..fa762d4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,6 +4,9 @@ ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign subdir-objects
SUBDIRS = libiptc libxtables
+if ENABLE_NFTABLES
+SUBDIRS += libnfttrans
+endif
if ENABLE_DEVEL
SUBDIRS += include
endif
diff --git a/configure.ac b/configure.ac
index 68f661c..4ca6f65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -207,6 +207,7 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
libiptc/Makefile libiptc/libiptc.pc
libiptc/libip4tc.pc libiptc/libip6tc.pc
libxtables/Makefile utils/Makefile
+ libnfttrans/Makefile libnfttrans/libnfttrans.pc
include/xtables-version.h include/iptables/internal.h])
AC_OUTPUT
diff --git a/include/nft-translator.h b/include/nft-translator.h
new file mode 100644
index 0000000..318f248
--- /dev/null
+++ b/include/nft-translator.h
@@ -0,0 +1,81 @@
+/*
+ * (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _NFT_TRANSLATOR_H
+#define _NFT_TRANSLATOR_H
+
+#include <stdint.h>
+#include <libnftables/rule.h>
+#include <libnftables/expr.h>
+
+enum nft_instruction {
+ NFT_INSTRUCTION_BITWISE = 0,
+ NFT_INSTRUCTION_BYTEORDER = 1,
+ NFT_INSTRUCTION_CMP = 2,
+ NFT_INSTRUCTION_COUNTER = 3,
+ NFT_INSTRUCTION_CT = 4,
+ NFT_INSTRUCTION_EXTHDR = 5,
+ NFT_INSTRUCTION_IMMEDIATE = 6,
+ NFT_INSTRUCTION_LIMIT = 7,
+ NFT_INSTRUCTION_LOG = 8,
+ NFT_INSTRUCTION_LOOKUP = 9,
+ NFT_INSTRUCTION_MATCH = 10,
+ NFT_INSTRUCTION_META = 11,
+ NFT_INSTRUCTION_NAT = 12,
+ NFT_INSTRUCTION_PAYLOAD = 13,
+ NFT_INSTRUCTION_REJECT = 14,
+ NFT_INSTRUCTION_TARGET = 15,
+ NFT_INSTRUCTION_MAX = 16,
+};
+
+struct nft_trans_instruction_tree;
+struct nft_trans_rule_context;
+struct nft_trans_instruction_context;
+
+typedef int (*nft_trans_parse_callback_f)(const char *ident,
+ void *data,
+ void *user_data);
+
+typedef int
+(*nft_trans_parse_instruction_f)(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_trans_instruction {
+ enum nft_instruction *instructions;
+ nft_trans_parse_instruction_f function;
+};
+
+struct nft_trans_instruction_tree *nft_trans_instruction_tree_new(void);
+
+void
+nft_trans_instruction_tree_destroy(struct nft_trans_instruction_tree *tree);
+
+int nft_trans_add_instruction(struct nft_trans_instruction_tree *tree,
+ struct nft_trans_instruction *ipt_i);
+
+int
+nft_trans_rule_translate_to_instructions(struct nft_trans_instruction_tree *tree,
+ struct nft_rule *rule,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data);
+
+struct nft_trans_instruction_context *
+nft_trans_instruction_context_get_next(struct nft_trans_instruction_context *i_ctx);
+
+struct nft_rule_expr *
+nft_trans_instruction_context_get_expr(struct nft_trans_instruction_context *i_ctx);
+
+struct nft_rule_expr *
+nft_trans_instruction_context_get_register(struct nft_trans_instruction_context *i_ctx,
+ int reg);
+
+#endif /* _NFT_TRANSLATOR_H */
diff --git a/libnfttrans/Makefile.am b/libnfttrans/Makefile.am
new file mode 100644
index 0000000..5befb63
--- /dev/null
+++ b/libnfttrans/Makefile.am
@@ -0,0 +1,28 @@
+# -*- Makefile -*-
+if ENABLE_NFTABLES
+if HAVE_LIBMNL
+if HAVE_LIBNFTABLES
+
+AM_CFLAGS = ${regular_CFLAGS}
+AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include \
+ -I${top_srcdir}/include -I./ ${kinclude_CPPFLAGS}
+
+lib_LTLIBRARIES = libnfttrans.la
+libnfttrans_la_SOURCES = nft-translator.c
+libnfttrans_la_LDFLAGS =
+libnfttrans_la_LIBADD =
+if ENABLE_STATIC
+# With --enable-static, shipped extensions are linked into the main executable,
+# so we need all the LIBADDs here too
+libnfttrans_la_LIBADD += -lm
+endif
+if ENABLE_SHARED
+libnfttrans_la_CFLAGS = ${AM_CFLAGS}
+libnfttrans_la_LIBADD += -ldl
+else
+libnfttrans_la_CFLAGS = ${AM_CFLAGS} -DNO_SHARED_LIBS=1
+endif
+
+endif # HAVE_LIBNFTABLES
+endif # HAVE_LIBMNL
+endif # ENABLE_NFTABLES
diff --git a/libnfttrans/libnfttrans.pc b/libnfttrans/libnfttrans.pc
new file mode 100644
index 0000000..fe0b4c0
--- /dev/null
+++ b/libnfttrans/libnfttrans.pc
@@ -0,0 +1,11 @@
+
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libnfttrans
+Description: Small engine to translate nft expressions list into more complex registered subset
+Version: 1.4.19.1
+Libs: -L${libdir} -lnfttrans
+Cflags: -I${includedir}
diff --git a/libnfttrans/libnfttrans.pc.in b/libnfttrans/libnfttrans.pc.in
new file mode 100644
index 0000000..f3363de
--- /dev/null
+++ b/libnfttrans/libnfttrans.pc.in
@@ -0,0 +1,11 @@
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libnfttrans
+Description: Small engine to translate nft expressions list into more complex registered subset
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lnfttrans
+Cflags: -I${includedir}
diff --git a/libnfttrans/nft-translator.c b/libnfttrans/nft-translator.c
new file mode 100644
index 0000000..12bd7e5
--- /dev/null
+++ b/libnfttrans/nft-translator.c
@@ -0,0 +1,571 @@
+/*
+ * (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <linux/netfilter/nf_tables.h>
+
+#include <nft-translator.h>
+
+static const char *nft_instruction_name[NFT_INSTRUCTION_MAX] = {
+ "bitwise",
+ "byteorder",
+ "cmp",
+ "counter",
+ "ct",
+ "exthdr",
+ "immediate",
+ "limit",
+ "log",
+ "lookup",
+ "match",
+ "meta",
+ "nat",
+ "payload",
+ "reject",
+ "target",
+};
+
+typedef void (*free_function_f)(void *);
+
+struct s_list {
+ void *data;
+ struct s_list *next;
+};
+
+struct nft_trans_instruction_node {
+ struct s_list *functions;
+ struct nft_trans_instruction_node *nodes[NFT_INSTRUCTION_MAX];
+};
+
+struct nft_trans_instruction_tree {
+ struct s_list *nodes;
+ struct nft_trans_instruction_node *root;
+};
+
+struct nft_trans_register_context {
+ struct nft_rule_expr *reg[NFT_REG_MAX];
+};
+
+struct nft_trans_instruction_context {
+ struct nft_trans_instruction_context *next;
+
+ struct nft_rule_expr *current_expr;
+ enum nft_instruction instruction;
+ struct nft_trans_register_context *registers;
+};
+
+struct nft_trans_rule_context {
+ struct nft_trans_instruction_context *instr_contexts;
+};
+
+struct nft_trans_found_instruction {
+ const struct s_list *functions;
+ struct nft_trans_instruction_context *position;
+};
+
+static enum nft_instruction str2nft_intruction(const char *name)
+{
+ enum nft_instruction i;
+
+ for (i = 0; i < NFT_INSTRUCTION_MAX; i++) {
+ if (strncmp(nft_instruction_name[i], name,
+ strlen(nft_instruction_name[i])) == 0)
+ return i;
+ }
+
+ return NFT_INSTRUCTION_MAX;
+}
+
+static struct s_list *s_list_prepend(struct s_list *list, void *data)
+{
+ struct s_list *n_list;
+
+ n_list = calloc(1, sizeof(struct s_list));
+ if (n_list == NULL)
+ return list;
+
+ n_list->data = data;
+ n_list->next = list;
+
+ return n_list;
+}
+
+static void s_list_free(struct s_list *list, int data_too,
+ free_function_f _free)
+{
+ struct s_list *previous = NULL;
+
+ for (; list != NULL; list = list->next) {
+ if (previous != NULL) {
+ if (previous->data != NULL && data_too != 0) {
+ if (_free != NULL)
+ _free(previous->data);
+ else
+ free(previous->data);
+ }
+
+ free(previous);
+ }
+
+ previous = list;
+ }
+
+ if (previous != NULL) {
+ if (previous->data != NULL && data_too != 0) {
+ if (_free != NULL)
+ _free(previous->data);
+ else
+ free(previous->data);
+ }
+
+ free(previous);
+ }
+}
+
+struct nft_trans_instruction_tree *nft_trans_instruction_tree_new(void)
+{
+ struct nft_trans_instruction_tree *tree;
+
+ tree = calloc(1, sizeof(struct nft_trans_instruction_tree));
+ if (tree != NULL) {
+ tree->root = calloc(1, sizeof(struct nft_trans_instruction_node));
+ if (tree->root == NULL)
+ goto error;
+
+ tree->nodes = s_list_prepend(tree->nodes, tree->root);
+ if (tree->nodes == NULL)
+ goto error;
+ }
+
+ return tree;
+
+error:
+ free(tree);
+ return NULL;
+}
+
+static void _free_nft_trans_instruction_node(void *data)
+{
+ struct nft_trans_instruction_node *node = data;
+
+ if (node == NULL)
+ return;
+
+ s_list_free(node->functions, 0, NULL);
+ free(node);
+}
+
+void
+nft_trans_instruction_tree_destroy(struct nft_trans_instruction_tree *tree)
+{
+ if (tree == NULL)
+ return;
+
+ s_list_free(tree->nodes, 1, _free_nft_trans_instruction_node);
+ free(tree);
+}
+
+int nft_trans_add_instruction(struct nft_trans_instruction_tree *tree,
+ struct nft_trans_instruction *ipt_i)
+{
+ struct nft_trans_instruction_node *node;
+ enum nft_instruction *instr;
+
+ if (tree == NULL)
+ return -EINVAL;
+
+ node = tree->root;
+ for (instr = ipt_i->instructions;
+ *instr < NFT_INSTRUCTION_MAX; instr++) {
+ if (node->nodes[*instr] == NULL) {
+ node->nodes[*instr] = calloc(1,
+ sizeof(struct nft_trans_instruction_node));
+ if (node->nodes[*instr] == NULL)
+ return -ENOMEM;
+ }
+
+ node = node->nodes[*instr];
+ tree->nodes = s_list_prepend(tree->nodes, node);
+ }
+
+ node->functions = s_list_prepend(node->functions, ipt_i->function);
+
+ return 0;
+}
+
+static void
+free_nft_trans_instruction_context(struct nft_trans_instruction_context *i_ctx)
+{
+ if (i_ctx == NULL)
+ return;
+
+ free(i_ctx->registers);
+ free(i_ctx);
+}
+
+static void
+destroy_nft_trans_rule_context(struct nft_trans_rule_context *rule_ctx)
+{
+ if (rule_ctx == NULL)
+ return;
+
+ if (rule_ctx->instr_contexts != NULL) {
+ struct nft_trans_instruction_context *i_ctx, *prev = NULL;
+
+ for (i_ctx = rule_ctx->instr_contexts;
+ i_ctx != NULL; i_ctx = i_ctx->next) {
+ free_nft_trans_instruction_context(prev);
+ prev = i_ctx;
+ }
+
+ free_nft_trans_instruction_context(prev);
+ }
+
+ free(rule_ctx);
+}
+
+static void
+update_register_from_bitwise(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_BITWISE_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_BITWISE_DREG)] = expr;
+}
+
+static void
+update_register_from_byteorder(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_BYTEORDER_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_BYTEORDER_DREG)] = expr;
+}
+
+static void
+update_register_from_ct(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_CT_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_CT_DREG)] = expr;
+}
+
+static void
+update_register_from_exthdr(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_EXTHDR_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_EXTHDR_DREG)] = expr;
+}
+
+static void
+update_register_from_immediate(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_IMM_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_IMM_DREG)] = expr;
+}
+
+static void
+update_register_from_lookup(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_LOOKUP_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_LOOKUP_DREG)] = expr;
+}
+
+static void
+update_register_from_meta(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_META_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_META_DREG)] = expr;
+}
+
+static void
+update_register_from_payload(struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ if (nft_rule_expr_is_set(expr, NFT_EXPR_PAYLOAD_DREG))
+ registers->reg[nft_rule_expr_get_u32(expr,
+ NFT_EXPR_PAYLOAD_DREG)] = expr;
+}
+
+static struct nft_trans_register_context *
+update_registers(enum nft_instruction instruction, struct nft_rule_expr *expr,
+ struct nft_trans_register_context *registers)
+{
+ struct nft_trans_register_context *new_registers;
+
+ new_registers = calloc(1, sizeof(struct nft_trans_register_context));
+ if (new_registers == NULL)
+ return NULL;
+
+ memcpy(new_registers, registers, sizeof(struct nft_trans_register_context));
+
+ switch (instruction) {
+ case NFT_INSTRUCTION_BITWISE:
+ update_register_from_bitwise(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_BYTEORDER:
+ update_register_from_byteorder(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_CMP:
+ case NFT_INSTRUCTION_COUNTER:
+ break;
+ case NFT_INSTRUCTION_CT:
+ update_register_from_ct(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_EXTHDR:
+ update_register_from_exthdr(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_IMMEDIATE:
+ update_register_from_immediate(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_LIMIT:
+ case NFT_INSTRUCTION_LOG:
+ break;
+ case NFT_INSTRUCTION_LOOKUP:
+ update_register_from_lookup(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_MATCH:
+ break;
+ case NFT_INSTRUCTION_META:
+ update_register_from_meta(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_NAT:
+ break;
+ case NFT_INSTRUCTION_PAYLOAD:
+ update_register_from_payload(expr, new_registers);
+ break;
+ case NFT_INSTRUCTION_REJECT:
+ case NFT_INSTRUCTION_TARGET:
+ break;
+ case NFT_INSTRUCTION_MAX:
+ return NULL;
+ };
+
+ return new_registers;
+}
+
+static struct nft_trans_rule_context *
+generate_nft_trans_rule_context(struct nft_rule *rule)
+{
+ struct nft_trans_instruction_context *cur_ctx = NULL;
+ struct nft_trans_register_context *cur_regs = NULL;
+ struct nft_trans_rule_context *rule_ctx;
+ struct nft_rule_expr_iter *iter;
+ struct nft_rule_expr *expr;
+
+ rule_ctx = calloc(1, sizeof(struct nft_trans_rule_context));
+ if (rule_ctx == NULL)
+ return NULL;
+
+ iter = nft_rule_expr_iter_create(rule);
+ if (iter == NULL)
+ goto error;
+
+ cur_regs = calloc(1, sizeof(struct nft_trans_register_context));
+ if (cur_regs == NULL)
+ goto error;
+
+ expr = nft_rule_expr_iter_next(iter);
+ while (expr != NULL) {
+ struct nft_trans_instruction_context *ctx;
+ enum nft_instruction instr;
+
+ ctx = calloc(1, sizeof(struct nft_trans_instruction_context));
+ if (ctx == NULL)
+ goto error;
+
+ instr = str2nft_intruction(nft_rule_expr_get_str(expr,
+ NFT_RULE_EXPR_ATTR_NAME));
+ if (instr == NFT_INSTRUCTION_MAX)
+ goto error;
+
+ ctx->current_expr = expr;
+ ctx->instruction = instr;
+ ctx->registers = cur_regs;
+
+ if (cur_ctx == NULL)
+ rule_ctx->instr_contexts = ctx;
+ else
+ cur_ctx->next = ctx;
+
+ cur_ctx = ctx;
+
+ cur_regs = update_registers(instr, expr, cur_regs);
+ if (cur_regs == NULL)
+ goto error;
+
+ expr = nft_rule_expr_iter_next(iter);
+ }
+
+ if (cur_regs != NULL)
+ free(cur_regs);
+
+ nft_rule_expr_iter_destroy(iter);
+
+ return rule_ctx;
+
+error:
+ destroy_nft_trans_rule_context(rule_ctx);
+
+ if (cur_regs != NULL)
+ free(cur_regs);
+
+ if (iter != NULL)
+ nft_rule_expr_iter_destroy(iter);
+
+ return NULL;
+}
+
+static struct s_list *
+retrieve_nft_trans_instructions(struct nft_trans_instruction_tree *tree,
+ struct nft_trans_instruction_context *instructions)
+{
+ struct s_list *nft_trans_instructions = NULL;
+ struct nft_trans_instruction_context *ctx;
+ struct nft_trans_found_instruction *ipt_i;
+ struct nft_trans_instruction_node *node;
+
+ ctx = instructions;
+ node = tree->root;
+
+ while (ctx != NULL) {
+ if (node->nodes[ctx->instruction] != NULL) {
+ node = node->nodes[ctx->instruction];
+
+ if (node->functions != NULL) {
+ ipt_i = calloc(1,
+ sizeof(struct nft_trans_found_instruction));
+
+ ipt_i->functions = node->functions;
+ ipt_i->position = ctx;
+
+ /* It prepends since "longest path first"
+ * is applied */
+ nft_trans_instructions = s_list_prepend(
+ nft_trans_instructions, ipt_i);
+ }
+ } else
+ break;
+
+ ctx = ctx->next;
+ };
+
+ return nft_trans_instructions;
+}
+
+static struct nft_trans_instruction_context *
+execute_relevant_instruction(struct s_list *instructions,
+ struct nft_trans_rule_context *rule_ctx,
+ struct nft_trans_instruction_context *position,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
+{
+ for (; instructions != NULL; instructions = instructions->next) {
+ struct nft_trans_found_instruction *i_f = instructions->data;
+ const struct s_list *fl;
+
+ for (fl = i_f->functions; fl != NULL; fl = fl->next) {
+ nft_trans_parse_instruction_f function = fl->data;
+
+ if (function(rule_ctx, position, i_f->position,
+ user_cb, user_data) == 0)
+ return i_f->position;
+ }
+ }
+
+ return NULL;
+}
+
+int
+nft_trans_rule_translate_to_instructions(struct nft_trans_instruction_tree *tree,
+ struct nft_rule *rule,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
+{
+ struct nft_trans_instruction_context *position;
+ struct s_list *nft_trans_instructions;
+ struct nft_trans_rule_context *rule_ctx;
+
+ if (tree == NULL)
+ return -1;
+
+ rule_ctx = generate_nft_trans_rule_context(rule);
+ if (rule_ctx == NULL)
+ return -1;
+
+ position = rule_ctx->instr_contexts;
+ while (position != NULL) {
+ struct nft_trans_instruction_context *pos;
+
+ nft_trans_instructions = retrieve_nft_trans_instructions(tree,
+ position);
+ if (nft_trans_instructions == NULL)
+ goto error;
+
+ pos = execute_relevant_instruction(nft_trans_instructions,
+ rule_ctx, position, user_cb, user_data);
+ if (pos == NULL)
+ goto error;
+
+ s_list_free(nft_trans_instructions, 1, NULL);
+ position = pos->next;
+ }
+
+ destroy_nft_trans_rule_context(rule_ctx);
+
+ return 0;
+
+error:
+ s_list_free(nft_trans_instructions, 1, NULL);
+ destroy_nft_trans_rule_context(rule_ctx);
+
+ return -1;
+}
+
+struct nft_trans_instruction_context *
+nft_trans_instruction_context_get_next(struct nft_trans_instruction_context *i_ctx)
+{
+ if (i_ctx == NULL)
+ return NULL;
+
+ return i_ctx->next;
+}
+
+struct nft_rule_expr *
+nft_trans_instruction_context_get_expr(struct nft_trans_instruction_context *i_ctx)
+{
+ if (i_ctx == NULL)
+ return NULL;
+
+ return i_ctx->current_expr;
+}
+
+struct nft_rule_expr *
+nft_trans_instruction_context_get_register(struct nft_trans_instruction_context *i_ctx,
+ int register_index)
+{
+ if (i_ctx == NULL || i_ctx->registers == NULL ||
+ register_index >= NFT_REG_MAX)
+ return NULL;
+
+ return i_ctx->registers->reg[register_index];
+}
+
--
1.8.3.2
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 04/16] nft: Integrate nft translator engine in current core
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (2 preceding siblings ...)
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 ` Tomasz Bursztyka
2013-08-09 21:24 ` Pablo Neira Ayuso
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 05/16] nft: Manage xtables target parsing through translation tree Tomasz Bursztyka
` (11 subsequent siblings)
15 siblings, 1 reply; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
First step of using the nft translation engine: supporting basic rule
information to recreat the command structure.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/Makefile.am | 2 +-
iptables/nft-ipv4.c | 23 ++++-
iptables/nft-ipv6.c | 9 +-
iptables/nft-shared.c | 255 ++++++++++++++++++++++++++++++++++++--------------
iptables/nft-shared.h | 16 +++-
iptables/nft.c | 3 +
6 files changed, 224 insertions(+), 84 deletions(-)
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index dc8af34..3a7983c 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -32,7 +32,7 @@ xtables_multi_SOURCES += xtables-save.c xtables-restore.c \
xtables-standalone.c xtables.c nft.c \
nft-shared.c nft-ipv4.c nft-ipv6.c \
xtables-config.c xtables-events.c
-xtables_multi_LDADD += -lmnl -lnftables ${libmnl_LIBS} ${libnftables_LIBS}
+xtables_multi_LDADD += -lmnl -lnftables ${libmnl_LIBS} ${libnftables_LIBS} ../libnfttrans/libnfttrans.la
xtables_multi_CFLAGS += -DENABLE_NFTABLES
# yacc and lex generate dirty code
xtables_multi-xtables-config-parser.o xtables_multi-xtables-config-syntax.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-missing-declarations -Wno-implicit-function-declaration -Wno-nested-externs -Wno-undef -Wno-redundant-decls
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 81be9f4..038d04f 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -85,6 +85,18 @@ static bool nft_ipv4_is_same(const struct iptables_command_state *a,
b->fw.ip.iniface_mask, b->fw.ip.outiface_mask);
}
+static void get_frag_from_expr(struct nft_rule_expr *e, bool *inv)
+{
+ uint8_t op;
+
+ /* e is directly pointing to the cmp expr */
+ op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP);
+ if (op == NFT_CMP_EQ)
+ *inv = true;
+ else
+ *inv = false;
+}
+
static void get_frag(struct nft_rule_expr_iter *iter, bool *inv)
{
struct nft_rule_expr *e;
@@ -207,7 +219,8 @@ static void nft_ipv4_parse_meta(struct nft_rule_expr *e, uint8_t key,
&cs->fw.ip.invflags);
}
-static void nft_ipv4_parse_payload(struct nft_rule_expr_iter *iter,
+static void nft_ipv4_parse_payload(struct nft_rule_expr *e_1,
+ struct nft_rule_expr *e_2,
struct iptables_command_state *cs,
uint32_t offset)
{
@@ -217,28 +230,28 @@ static void nft_ipv4_parse_payload(struct nft_rule_expr_iter *iter,
bool inv;
case offsetof(struct iphdr, saddr):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ get_expr_cmp_data(e_1, &addr, sizeof(addr), &inv);
cs->fw.ip.src.s_addr = addr.s_addr;
cs->fw.ip.smsk.s_addr = 0xffffffff;
if (inv)
cs->fw.ip.invflags |= IPT_INV_SRCIP;
break;
case offsetof(struct iphdr, daddr):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ get_expr_cmp_data(e_1, &addr, sizeof(addr), &inv);
cs->fw.ip.dst.s_addr = addr.s_addr;
cs->fw.ip.dmsk.s_addr = 0xffffffff;
if (inv)
cs->fw.ip.invflags |= IPT_INV_DSTIP;
break;
case offsetof(struct iphdr, protocol):
- get_cmp_data(iter, &proto, sizeof(proto), &inv);
+ get_expr_cmp_data(e_1, &proto, sizeof(proto), &inv);
cs->fw.ip.proto = proto;
if (inv)
cs->fw.ip.invflags |= IPT_INV_PROTO;
break;
case offsetof(struct iphdr, frag_off):
cs->fw.ip.flags |= IPT_F_FRAG;
- get_frag(iter, &inv);
+ get_frag_from_expr(e_2, &inv);
if (inv)
cs->fw.ip.invflags |= IPT_INV_FRAG;
break;
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 0214dcf..5c79912 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -119,7 +119,8 @@ static void nft_ipv6_parse_meta(struct nft_rule_expr *e, uint8_t key,
cs->fw6.ipv6.outiface_mask, &cs->fw6.ipv6.invflags);
}
-static void nft_ipv6_parse_payload(struct nft_rule_expr_iter *iter,
+static void nft_ipv6_parse_payload(struct nft_rule_expr *e_1,
+ struct nft_rule_expr *e_2,
struct iptables_command_state *cs,
uint32_t offset)
{
@@ -129,19 +130,19 @@ static void nft_ipv6_parse_payload(struct nft_rule_expr_iter *iter,
bool inv;
case offsetof(struct ip6_hdr, ip6_src):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ get_expr_cmp_data(e_1, &addr, sizeof(addr), &inv);
memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr));
if (inv)
cs->fw6.ipv6.invflags |= IPT_INV_SRCIP;
break;
case offsetof(struct ip6_hdr, ip6_dst):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ get_expr_cmp_data(e_1, &addr, sizeof(addr), &inv);
memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr));
if (inv)
cs->fw6.ipv6.invflags |= IPT_INV_DSTIP;
break;
case offsetof(struct ip6_hdr, ip6_nxt):
- get_cmp_data(iter, &proto, sizeof(proto), &inv);
+ get_expr_cmp_data(e_1, &proto, sizeof(proto), &inv);
cs->fw6.ipv6.flags |= IP6T_F_PROTO;
cs->fw6.ipv6.proto = proto;
if (inv)
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index dd4766b..614b7ae 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -28,6 +28,8 @@
#include "nft-shared.h"
#include "xshared.h"
+struct nft_trans_instruction_tree *xt_nft_tree;
+
extern struct nft_family_ops nft_family_ops_ipv4;
extern struct nft_family_ops nft_family_ops_ipv6;
@@ -349,21 +351,16 @@ void print_proto(uint16_t proto, int invert)
printf("-p %u ", proto);
}
-void get_cmp_data(struct nft_rule_expr_iter *iter,
- void *data, size_t dlen, bool *inv)
+void get_expr_cmp_data(struct nft_rule_expr *e,
+ void *data, size_t dlen, bool *inv)
{
- struct nft_rule_expr *e;
const char *name;
size_t len;
uint8_t op;
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
+ DEBUGP("skipping - Not a cmp expression\n");
return;
}
@@ -375,105 +372,154 @@ void get_cmp_data(struct nft_rule_expr_iter *iter,
*inv = false;
}
-static void
-nft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- int family, struct iptables_command_state *cs)
+void get_cmp_data(struct nft_rule_expr_iter *iter,
+ void *data, size_t dlen, bool *inv)
{
- uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
- struct nft_family_ops *ops = nft_family_ops_lookup(family);
- const char *name;
+ struct nft_rule_expr *e;
e = nft_rule_expr_iter_next(iter);
if (e == NULL)
return;
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
- return;
- }
-
- ops->parse_meta(e, key, cs);
+ get_expr_cmp_data(e, data, dlen, inv);
}
-static void
-nft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- int family, struct iptables_command_state *cs)
+static int
+nft_parse_counters(struct nft_trans_rule_context *rule_ctx,
+ struct nft_trans_instruction_context *first,
+ struct nft_trans_instruction_context *useless,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
{
- struct nft_family_ops *ops = nft_family_ops_lookup(family);
- uint32_t offset;
+ struct nft_to_cs_data *i2cs = user_data;
+ struct xt_counters *counters;
+ struct nft_rule_expr *e;
- offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+ e = nft_trans_instruction_context_get_expr(first);
- ops->parse_payload(iter, cs, offset);
-}
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_CTR_PACKETS) ||
+ !nft_rule_expr_is_set(e, NFT_EXPR_CTR_BYTES))
+ return -1;
-static void
-nft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- struct xt_counters *counters)
-{
+ counters = &i2cs->cs->counters;
counters->pcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS);
counters->bcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES);
+
+ return 0;
}
-static void
-nft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- int family, struct iptables_command_state *cs)
+static int
+nft_parse_verdict(struct nft_trans_rule_context *rule_ctx,
+ struct nft_trans_instruction_context *first,
+ struct nft_trans_instruction_context *useless,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
{
- int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
- const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
+ struct nft_to_cs_data *i2cs = user_data;
struct nft_family_ops *ops;
+ struct nft_rule_expr *e;
+ const char *chain;
+ int verdict;
+
+ e = nft_trans_instruction_context_get_expr(first);
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_IMM_VERDICT))
+ return -1;
+ verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
/* Standard target? */
switch(verdict) {
case NF_ACCEPT:
- cs->jumpto = "ACCEPT";
- return;
+ i2cs->cs->jumpto = "ACCEPT";
+ break;
case NF_DROP:
- cs->jumpto = "DROP";
- return;
+ i2cs->cs->jumpto = "DROP";
+ break;
case NFT_RETURN:
- cs->jumpto = "RETURN";
- return;
+ i2cs->cs->jumpto = "RETURN";
+ break;
case NFT_GOTO:
- ops = nft_family_ops_lookup(family);
- ops->parse_immediate(cs);
+ ops = nft_family_ops_lookup(i2cs->family);
+ ops->parse_immediate(i2cs->cs);
case NFT_JUMP:
- cs->jumpto = chain;
- return;
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_IMM_CHAIN))
+ return -1;
+
+ chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
+ i2cs->cs->jumpto = chain;
+ break;
}
+
+ return 0;
}
-void nft_rule_to_iptables_command_state(struct nft_rule *r,
- struct iptables_command_state *cs)
+static int nft_parse_io_ifs(struct nft_trans_rule_context *rule_ctx,
+ struct nft_trans_instruction_context *first,
+ struct nft_trans_instruction_context *second,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
+ struct nft_to_cs_data *i2cs = user_data;
+ struct nft_family_ops *ops;
+ struct nft_rule_expr *e;
+ uint8_t key;
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return;
+ e = nft_trans_instruction_context_get_expr(first);
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_META_KEY))
+ return -1;
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
+ key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
+ ops = nft_family_ops_lookup(i2cs->family);
- if (strcmp(name, "counter") == 0) {
- nft_parse_counter(expr, iter, &cs->counters);
- } else if (strcmp(name, "payload") == 0) {
- nft_parse_payload(expr, iter, family, cs);
- } else if (strcmp(name, "meta") == 0) {
- nft_parse_meta(expr, iter, family, cs);
- } else if (strcmp(name, "immediate") == 0) {
- nft_parse_immediate(expr, iter, family, cs);
- }
+ e = nft_trans_instruction_context_get_expr(second);
+ ops->parse_meta(e, key, i2cs->cs);
- expr = nft_rule_expr_iter_next(iter);
- }
+ return 0;
+}
- nft_rule_expr_iter_destroy(iter);
+static int nft_parse_ip_addresses(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_to_cs_data *i2cs = user_data;
+ struct nft_rule_expr *e1, *e2;
+ struct nft_family_ops *ops;
+ uint32_t offset;
+
+ e1 = nft_trans_instruction_context_get_expr(first);
+ if (!nft_rule_expr_is_set(e1, NFT_EXPR_PAYLOAD_OFFSET))
+ return -1;
+
+ offset = nft_rule_expr_get_u32(e1, NFT_EXPR_PAYLOAD_OFFSET);
+ ops = nft_family_ops_lookup(i2cs->family);
+
+ first = nft_trans_instruction_context_get_next(first);
+ e1 = nft_trans_instruction_context_get_expr(first);
+ e2 = nft_trans_instruction_context_get_expr(last);
+
+ ops->parse_payload(e1, e2, i2cs->cs, offset);
+
+ return 0;
+}
+
+void nft_rule_to_iptables_command_state(struct nft_rule *r,
+ struct iptables_command_state *cs)
+{
+ struct nft_to_cs_data i2cs = {};
+
+ i2cs.family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
+ i2cs.cs = cs;
+
+ nft_trans_rule_translate_to_instructions(xt_nft_tree, r, NULL, &i2cs);
+
+ if (i2cs.cs->target != NULL)
+ i2cs.cs->jumpto = i2cs.cs->target->name;
+ else if (i2cs.cs->jumpto != NULL)
+ i2cs.cs->target = xtables_find_target(i2cs.cs->jumpto,
+ XTF_TRY_LOAD);
+ else
+ i2cs.cs->jumpto = "";
}
static void
@@ -646,6 +692,71 @@ void print_firewall_details(const struct iptables_command_state *cs,
}
}
+static enum nft_instruction nft_ipt_counters_instructions[] = {
+ NFT_INSTRUCTION_COUNTER,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_counters = {
+ .instructions = nft_ipt_counters_instructions,
+ .function = nft_parse_counters,
+};
+
+static enum nft_instruction nft_ipt_verdict_instructions[] = {
+ NFT_INSTRUCTION_IMMEDIATE,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_verdict = {
+ .instructions = nft_ipt_verdict_instructions,
+ .function = nft_parse_verdict,
+};
+
+static enum nft_instruction nft_ipt_io_ifs_instructions[] = {
+ NFT_INSTRUCTION_META, NFT_INSTRUCTION_CMP,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_io_ifs = {
+ .instructions = nft_ipt_io_ifs_instructions,
+ .function = nft_parse_io_ifs,
+};
+
+static enum nft_instruction nft_ipt_ip_addr_instructions_1[] = {
+ NFT_INSTRUCTION_PAYLOAD, NFT_INSTRUCTION_CMP,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_ip_addr_1 = {
+ .instructions = nft_ipt_ip_addr_instructions_1,
+ .function = nft_parse_ip_addresses,
+};
+
+static enum nft_instruction nft_ipt_ip_addr_instructions_2[] = {
+ NFT_INSTRUCTION_PAYLOAD, NFT_INSTRUCTION_BITWISE, NFT_INSTRUCTION_CMP,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_ip_addr_2 = {
+ .instructions = nft_ipt_ip_addr_instructions_2,
+ .function = nft_parse_ip_addresses,
+};
+
+int nft_initiate_translation_tree(void)
+{
+ xt_nft_tree = nft_trans_instruction_tree_new();
+ if (xt_nft_tree == NULL)
+ return -1;
+
+ nft_trans_add_instruction(xt_nft_tree, &nft_ipt_counters);
+ nft_trans_add_instruction(xt_nft_tree, &nft_ipt_verdict);
+ nft_trans_add_instruction(xt_nft_tree, &nft_ipt_io_ifs);
+ nft_trans_add_instruction(xt_nft_tree, &nft_ipt_ip_addr_1);
+ nft_trans_add_instruction(xt_nft_tree, &nft_ipt_ip_addr_2);
+
+ return 0;
+}
+
struct nft_family_ops *nft_family_ops_lookup(int family)
{
switch (family) {
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 488ed63..176abed 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -6,6 +6,8 @@
#include <libnftables/rule.h>
#include <libnftables/expr.h>
+#include <nft-translator.h>
+
#include "xshared.h"
#if 0
@@ -34,6 +36,8 @@
| FMT_NUMERIC | FMT_NOTABLE)
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
+extern struct nft_trans_instruction_tree *xt_nft_tree;
+
struct xtables_args;
struct nft_family_ops {
@@ -44,7 +48,8 @@ struct nft_family_ops {
struct nft_rule_expr_iter *iter);
void (*parse_meta)(struct nft_rule_expr *e, uint8_t key,
struct iptables_command_state *cs);
- void (*parse_payload)(struct nft_rule_expr_iter *iter,
+ void (*parse_payload)(struct nft_rule_expr *e_1,
+ struct nft_rule_expr *e_2,
struct iptables_command_state *cs,
uint32_t offset);
void (*parse_immediate)(struct iptables_command_state *cs);
@@ -82,6 +87,8 @@ void parse_meta(struct nft_rule_expr *e, uint8_t key, char *iniface,
const char *nft_parse_target(struct nft_rule *r, const void **targinfo,
size_t *target_len);
void print_proto(uint16_t proto, int invert);
+void get_expr_cmp_data(struct nft_rule_expr *e,
+ void *data, size_t dlen, bool *inv);
void get_cmp_data(struct nft_rule_expr_iter *iter,
void *data, size_t dlen, bool *inv);
void nft_rule_to_iptables_command_state(struct nft_rule *r,
@@ -95,7 +102,7 @@ void print_firewall_details(const struct iptables_command_state *cs,
uint8_t invflags, uint8_t proto,
const char *iniface, const char *outiface,
unsigned int num, unsigned int format);
-
+int nft_initiate_translation_tree(void);
struct nft_family_ops *nft_family_ops_lookup(int family);
struct addr_mask {
@@ -126,6 +133,11 @@ struct xtables_args {
unsigned long long pcnt_cnt, bcnt_cnt;
};
+struct nft_to_cs_data {
+ int family;
+ struct iptables_command_state *cs;
+};
+
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
diff --git a/iptables/nft.c b/iptables/nft.c
index d92e8bb..7171752 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -388,6 +388,9 @@ int nft_init(struct nft_handle *h, struct builtin_table *t)
h->portid = mnl_socket_get_portid(h->nl);
h->tables = t;
+ if (nft_initiate_translation_tree() != 0)
+ return -1;
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 05/16] nft: Manage xtables target parsing through translation tree
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (3 preceding siblings ...)
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 13:31 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 06/16] nft: Manage xtables matches through nft " Tomasz Bursztyka
` (10 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
This add the support of compatible layer for xtables target extension through
the nft translator. Thus feeding give command structure with the right target.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/Makefile.am | 1 +
iptables/nft-shared.c | 3 ++
iptables/nft-xt-ext.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++
iptables/nft-xt-ext.h | 12 ++++++++
4 files changed, 101 insertions(+)
create mode 100644 iptables/nft-xt-ext.c
create mode 100644 iptables/nft-xt-ext.h
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index 3a7983c..7ba2990 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -31,6 +31,7 @@ xtables_multi_SOURCES += xtables-config-parser.y xtables-config-syntax.l
xtables_multi_SOURCES += xtables-save.c xtables-restore.c \
xtables-standalone.c xtables.c nft.c \
nft-shared.c nft-ipv4.c nft-ipv6.c \
+ nft-xt-ext.c \
xtables-config.c xtables-events.c
xtables_multi_LDADD += -lmnl -lnftables ${libmnl_LIBS} ${libnftables_LIBS} ../libnfttrans/libnfttrans.la
xtables_multi_CFLAGS += -DENABLE_NFTABLES
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 614b7ae..b3682c4 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -27,6 +27,7 @@
#include "nft-shared.h"
#include "xshared.h"
+#include "nft-xt-ext.h"
struct nft_trans_instruction_tree *xt_nft_tree;
@@ -754,6 +755,8 @@ int nft_initiate_translation_tree(void)
nft_trans_add_instruction(xt_nft_tree, &nft_ipt_ip_addr_1);
nft_trans_add_instruction(xt_nft_tree, &nft_ipt_ip_addr_2);
+ nft_xt_ext_into_translation_tree(xt_nft_tree);
+
return 0;
}
diff --git a/iptables/nft-xt-ext.c b/iptables/nft-xt-ext.c
new file mode 100644
index 0000000..70ffe35
--- /dev/null
+++ b/iptables/nft-xt-ext.c
@@ -0,0 +1,85 @@
+/*
+ * (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <xtables.h>
+
+#include <nft-xt-ext.h>
+#include <nft-shared.h>
+
+static int nft_parse_xt_target(struct nft_trans_rule_context *rule_ctx,
+ struct nft_trans_instruction_context *first,
+ struct nft_trans_instruction_context *useless,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
+{
+ struct nft_to_cs_data *i2cs = user_data;
+ struct xtables_target *target;
+ struct xt_entry_target *t;
+ struct nft_rule_expr *e;
+ const char *target_name;
+ const void *info;
+ size_t length;
+ uint32_t rev;
+
+ e = nft_trans_instruction_context_get_expr(first);
+
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_TG_NAME) ||
+ !nft_rule_expr_is_set(e, NFT_EXPR_TG_REV) ||
+ !nft_rule_expr_is_set(e, NFT_EXPR_TG_INFO))
+ return -1;
+
+ target_name = nft_rule_expr_get_str(e, NFT_EXPR_TG_NAME);
+ if (target_name == NULL)
+ return -1;
+
+ target = xtables_find_target(target_name, XTF_TRY_LOAD);
+ if (target == NULL)
+ return -1;
+
+ info = nft_rule_expr_get(e, NFT_EXPR_TG_INFO, &length);
+
+ t = calloc(1, sizeof(struct xt_entry_target) + length);
+ if (t == NULL)
+ return -1;
+
+ memcpy(&t->data, info, length);
+ t->u.target_size = length + XT_ALIGN(sizeof(struct xt_entry_target));
+
+ rev = nft_rule_expr_get_u32(e, NFT_EXPR_TG_REV);
+ t->u.user.revision = rev;
+ strcpy(t->u.user.name, target->name);
+
+ target->t = t;
+ i2cs->cs->target = target;
+
+ return 0;
+}
+
+static enum nft_instruction nft_ipt_xt_target_instructions[] = {
+ NFT_INSTRUCTION_TARGET,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_xt_target = {
+ .instructions = nft_ipt_xt_target_instructions,
+ .function = nft_parse_xt_target,
+};
+
+int nft_xt_ext_into_translation_tree(struct nft_trans_instruction_tree *tree)
+{
+ if (tree == NULL)
+ return -1;
+
+ nft_trans_add_instruction(tree, &nft_ipt_xt_target);
+
+ return 0;
+}
diff --git a/iptables/nft-xt-ext.h b/iptables/nft-xt-ext.h
new file mode 100644
index 0000000..a367277
--- /dev/null
+++ b/iptables/nft-xt-ext.h
@@ -0,0 +1,12 @@
+/*
+ * (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <nft-translator.h>
+
+int nft_xt_ext_into_translation_tree(struct nft_trans_instruction_tree *tree);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 06/16] nft: Manage xtables matches through nft translation tree
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (4 preceding siblings ...)
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 ` 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
` (9 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
This add the support of compatible layer for xtables matches extension through
the nft translator. Thus feeding give command structure with the right matches.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft-xt-ext.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/iptables/nft-xt-ext.c b/iptables/nft-xt-ext.c
index 70ffe35..f013493 100644
--- a/iptables/nft-xt-ext.c
+++ b/iptables/nft-xt-ext.c
@@ -64,6 +64,55 @@ static int nft_parse_xt_target(struct nft_trans_rule_context *rule_ctx,
return 0;
}
+static int nft_parse_xt_match(struct nft_trans_rule_context *rule_ctx,
+ struct nft_trans_instruction_context *first,
+ struct nft_trans_instruction_context *useless,
+ nft_trans_parse_callback_f user_cb,
+ void *user_data)
+{
+ struct nft_to_cs_data *i2cs = user_data;
+ struct xtables_match *match;
+ struct xt_entry_match *m;
+ struct nft_rule_expr *e;
+ const char *match_name;
+ const void *info;
+ size_t length;
+ uint32_t rev;
+
+ e = nft_trans_instruction_context_get_expr(first);
+
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_MT_NAME) ||
+ !nft_rule_expr_is_set(e, NFT_EXPR_MT_REV) ||
+ !nft_rule_expr_is_set(e, NFT_EXPR_MT_INFO))
+ return -1;
+
+ match_name = nft_rule_expr_get_str(e, NFT_EXPR_MT_NAME);
+ if (match_name == NULL)
+ return -1;
+
+ match = xtables_find_match(match_name,
+ XTF_TRY_LOAD, &i2cs->cs->matches);
+ if (match == NULL)
+ return -1;
+
+ info = nft_rule_expr_get(e, NFT_EXPR_TG_INFO, &length);
+
+ m = calloc(1, sizeof(struct xt_entry_match) + length);
+ if (m == NULL)
+ return -1;
+
+ memcpy(&m->data, info, length);
+ m->u.match_size = length + XT_ALIGN(sizeof(struct xt_entry_match));
+
+ rev = nft_rule_expr_get_u32(e, NFT_EXPR_TG_REV);
+ m->u.user.revision = rev;
+ strcpy(m->u.user.name, match->name);
+
+ match->m = m;
+
+ return 0;
+}
+
static enum nft_instruction nft_ipt_xt_target_instructions[] = {
NFT_INSTRUCTION_TARGET,
NFT_INSTRUCTION_MAX,
@@ -74,12 +123,23 @@ static struct nft_trans_instruction nft_ipt_xt_target = {
.function = nft_parse_xt_target,
};
+static enum nft_instruction nft_ipt_xt_match_instructions[] = {
+ NFT_INSTRUCTION_MATCH,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction nft_ipt_xt_match = {
+ .instructions = nft_ipt_xt_match_instructions,
+ .function = nft_parse_xt_match,
+};
+
int nft_xt_ext_into_translation_tree(struct nft_trans_instruction_tree *tree)
{
if (tree == NULL)
return -1;
nft_trans_add_instruction(tree, &nft_ipt_xt_target);
+ nft_trans_add_instruction(tree, &nft_ipt_xt_match);
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 07/16] nft: Add support for xtables extensions callback to change cs
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (5 preceding siblings ...)
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 ` 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
` (8 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
This add the support of xtables extension expressed in pure nft through
the nft translator. Thus feeding give command structure with the right
target or match. This has been implemented as a callback, in the core,
to let the extentions being able to feed the command structure. Which
command structure they cannot handle (its declaration is private to the core).
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft-shared.c | 3 ++-
iptables/nft-xt-ext.c | 20 ++++++++++++++++++++
iptables/nft-xt-ext.h | 2 ++
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index b3682c4..8bef696 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -512,7 +512,8 @@ void nft_rule_to_iptables_command_state(struct nft_rule *r,
i2cs.family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
i2cs.cs = cs;
- nft_trans_rule_translate_to_instructions(xt_nft_tree, r, NULL, &i2cs);
+ nft_trans_rule_translate_to_instructions(xt_nft_tree, r,
+ nft_xt_ext_parse_callback, &i2cs);
if (i2cs.cs->target != NULL)
i2cs.cs->jumpto = i2cs.cs->target->name;
diff --git a/iptables/nft-xt-ext.c b/iptables/nft-xt-ext.c
index f013493..660e417 100644
--- a/iptables/nft-xt-ext.c
+++ b/iptables/nft-xt-ext.c
@@ -143,3 +143,23 @@ int nft_xt_ext_into_translation_tree(struct nft_trans_instruction_tree *tree)
return 0;
}
+
+int nft_xt_ext_parse_callback(const char *ident, void *data, void *user_data)
+{
+ struct nft_to_cs_data *i2cs = user_data;
+ struct xtables_target *target;
+ struct xtables_match *match;
+
+ target = xtables_find_target(ident, XTF_TRY_LOAD);
+ match = xtables_find_match(ident, XTF_TRY_LOAD, &i2cs->cs->matches);
+
+ if (target != NULL) {
+ target->t = data;
+ i2cs->cs->target = target;
+ } else if (match != NULL)
+ match->m = data;
+ else
+ return -1;
+
+ return 0;
+}
diff --git a/iptables/nft-xt-ext.h b/iptables/nft-xt-ext.h
index a367277..f3e6491 100644
--- a/iptables/nft-xt-ext.h
+++ b/iptables/nft-xt-ext.h
@@ -10,3 +10,5 @@
#include <nft-translator.h>
int nft_xt_ext_into_translation_tree(struct nft_trans_instruction_tree *tree);
+
+int nft_xt_ext_parse_callback(const char *ident, void *data, void *user_data);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 08/16] xtables: Add support for registering nft translation function for target
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (6 preceding siblings ...)
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 ` 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
` (7 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Add the method which will be called by the core to register the xtables
target extensions into the nft translator. Through that method, the extension
will provide the combination of pattern/parser to the translation tree.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
extensions/GNUmakefile.in | 2 +-
include/xtables.h | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index da2f38b..5a19008 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -16,7 +16,7 @@ CCLD = ${CC}
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
-@ENABLE_NFTABLES_TRUE@ LDFLAGS += @EXTENSION_NFT_LDFLAGS@
+@ENABLE_NFTABLES_TRUE@ LDFLAGS += @EXTENSION_NFT_LDFLAGS@ -L../libnfttrans/.libs -lnfttrans
regular_CFLAGS = @regular_CFLAGS@
regular_CPPFLAGS = @regular_CPPFLAGS@
kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
diff --git a/include/xtables.h b/include/xtables.h
index 5bd8a59..fe1f31c 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -19,6 +19,7 @@
#include <linux/netfilter/x_tables.h>
#include <libnftables/rule.h>
+#include <nft-translator.h>
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
@@ -353,6 +354,7 @@ struct xtables_target
/* NFT related */
int (*to_nft)(struct nft_rule *, struct xt_entry_target *);
+ int (*register_nft_instructions)(struct nft_trans_instruction_tree *);
size_t udata_size;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 09/16] xtables: Add support for registering nft translation function for match
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (7 preceding siblings ...)
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 ` 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
` (6 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Add the method which will be called by the core to register the xtables
matches extensions into the nft translator. Through that method, the extension
will provide the combination of pattern/parser to the translation tree.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
include/xtables.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/xtables.h b/include/xtables.h
index fe1f31c..03139a0 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -274,6 +274,7 @@ struct xtables_match
/* NFT related */
int (*to_nft)(struct nft_rule *r, struct xt_entry_match *);
+ int (*register_nft_instructions)(struct nft_trans_instruction_tree *);
/* Size of per-extension instance extra "global" scratch space */
size_t udata_size;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 10/16] nft: Register all relevant xtables extensions into translation tree
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (8 preceding siblings ...)
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 ` 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
` (5 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
On the contrary of legacy code or current compatible xtables layer in nftables,
pure nft expression list, representing an extension, won't provide any extension
name.
What use to be one target expressions with a name and a data like for instance:
target(foo,<memory blob>)
will become:
imm bitwise cmp payload imm cmp
Thus, it's necessary to know the expression patterns, before hand to be able to
match the right extension.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
include/xtables.h | 2 ++
iptables/nft-xt-ext.c | 13 +++++++++++++
2 files changed, 15 insertions(+)
diff --git a/include/xtables.h b/include/xtables.h
index 03139a0..0a07f22 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -422,6 +422,8 @@ extern "C" {
#endif
extern const char *xtables_modprobe_program;
+extern struct xtables_match *xtables_pending_matches;
+extern struct xtables_target *xtables_pending_targets;
extern struct xtables_match *xtables_matches;
extern struct xtables_target *xtables_targets;
diff --git a/iptables/nft-xt-ext.c b/iptables/nft-xt-ext.c
index 660e417..b2b29a7 100644
--- a/iptables/nft-xt-ext.c
+++ b/iptables/nft-xt-ext.c
@@ -135,12 +135,25 @@ static struct nft_trans_instruction nft_ipt_xt_match = {
int nft_xt_ext_into_translation_tree(struct nft_trans_instruction_tree *tree)
{
+ struct xtables_target *t;
+ struct xtables_match *m;
+
if (tree == NULL)
return -1;
nft_trans_add_instruction(tree, &nft_ipt_xt_target);
nft_trans_add_instruction(tree, &nft_ipt_xt_match);
+ for (t = xtables_pending_targets; t; t = t->next) {
+ if (t->register_nft_instructions != NULL)
+ t->register_nft_instructions(tree);
+ }
+
+ for (m = xtables_pending_matches; m; m = m->next) {
+ if (m->register_nft_instructions != NULL)
+ m->register_nft_instructions(tree);
+ }
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 11/16] nft: Refactor firewall printing so it reuses already parsed cs struct
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (9 preceding siblings ...)
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 ` Tomasz Bursztyka
2013-08-09 21:51 ` Pablo Neira Ayuso
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 12/16] nft: Refactor rule deletion so it compares both cs structure Tomasz Bursztyka
` (4 subsequent siblings)
15 siblings, 1 reply; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Now that we parse properly, in one place and at once, the rule back into
a command structure, it's now easier to print the rule from that command
structure.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft-ipv4.c | 13 +----
iptables/nft-ipv6.c | 13 +----
iptables/nft-shared.c | 152 ++++++--------------------------------------------
iptables/nft-shared.h | 7 +--
4 files changed, 24 insertions(+), 161 deletions(-)
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 038d04f..02b52df 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -301,15 +301,10 @@ static void nft_ipv4_print_firewall(struct nft_rule *r, unsigned int num,
unsigned int format)
{
struct iptables_command_state cs = {};
- const char *targname = NULL;
- const void *targinfo = NULL;
- size_t target_len = 0;
nft_rule_to_iptables_command_state(r, &cs);
- targname = nft_parse_target(r, &targinfo, &target_len);
-
- print_firewall_details(&cs, targname, cs.fw.ip.flags,
+ print_firewall_details(&cs, cs.jumpto, cs.fw.ip.flags,
cs.fw.ip.invflags, cs.fw.ip.proto,
cs.fw.ip.iniface, cs.fw.ip.outiface,
num, format);
@@ -324,11 +319,7 @@ static void nft_ipv4_print_firewall(struct nft_rule *r, unsigned int num,
printf("[goto] ");
#endif
- if (print_matches(r, format) != 0)
- return;
-
- if (print_target(targname, targinfo, target_len, format) != 0)
- return;
+ print_matches_and_target(&cs, format);
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 5c79912..15c37f6 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -199,15 +199,10 @@ static void nft_ipv6_print_firewall(struct nft_rule *r, unsigned int num,
unsigned int format)
{
struct iptables_command_state cs = {};
- const char *targname = NULL;
- const void *targinfo = NULL;
- size_t target_len = 0;
nft_rule_to_iptables_command_state(r, &cs);
- targname = nft_parse_target(r, &targinfo, &target_len);
-
- print_firewall_details(&cs, targname, cs.fw6.ipv6.flags,
+ print_firewall_details(&cs, cs.jumpto, cs.fw6.ipv6.flags,
cs.fw6.ipv6.invflags, cs.fw6.ipv6.proto,
cs.fw6.ipv6.iniface, cs.fw6.ipv6.outiface,
num, format);
@@ -222,11 +217,7 @@ static void nft_ipv6_print_firewall(struct nft_rule *r, unsigned int num,
printf("[goto] ");
#endif
- if (print_matches(r, format) != 0)
- return;
-
- if (print_target(targname, targinfo, target_len, format) != 0)
- return;
+ print_matches_and_target(&cs, format);
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 8bef696..4eba145 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -284,59 +284,6 @@ void parse_meta(struct nft_rule_expr *e, uint8_t key, char *iniface,
}
}
-const char *nft_parse_target(struct nft_rule *r, const void **targinfo,
- size_t *target_len)
-{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- const char *targname = NULL;
-
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return NULL;
-
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
-
- if (strcmp(name, "target") == 0) {
- targname = nft_rule_expr_get_str(expr,
- NFT_EXPR_TG_NAME);
- *targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO,
- target_len);
- break;
- } else if (strcmp(name, "immediate") == 0) {
- uint32_t verdict =
- nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
-
- switch(verdict) {
- case NF_ACCEPT:
- targname = "ACCEPT";
- break;
- case NF_DROP:
- targname = "DROP";
- break;
- case NFT_RETURN:
- targname = "RETURN";
- break;
- case NFT_GOTO:
- targname = nft_rule_expr_get_str(expr,
- NFT_EXPR_IMM_CHAIN);
- break;
- case NFT_JUMP:
- targname = nft_rule_expr_get_str(expr,
- NFT_EXPR_IMM_CHAIN);
- break;
- }
- }
- expr = nft_rule_expr_iter_next(iter);
- }
- nft_rule_expr_iter_destroy(iter);
-
- return targname;
-}
-
void print_proto(uint16_t proto, int invert)
{
const struct protoent *pent = getprotobynumber(proto);
@@ -524,87 +471,6 @@ void nft_rule_to_iptables_command_state(struct nft_rule *r,
i2cs.cs->jumpto = "";
}
-static void
-print_match(struct nft_rule_expr *expr, int numeric)
-{
- size_t len;
- const char *match_name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
- const void *match_info = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
- const struct xtables_match *match =
- xtables_find_match(match_name, XTF_TRY_LOAD, NULL);
- struct xt_entry_match *m =
- calloc(1, sizeof(struct xt_entry_match) + len);
-
- /* emulate struct xt_entry_match since ->print needs it */
- memcpy((void *)&m->data, match_info, len);
-
- if (match) {
- if (match->print)
- /* FIXME missing first parameter */
- match->print(NULL, m, numeric);
- else
- printf("%s ", match_name);
- } else {
- if (match_name[0])
- printf("UNKNOWN match `%s' ", match_name);
- }
-
- free(m);
-}
-
-int print_matches(struct nft_rule *r, int format)
-{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
-
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return -ENOMEM;
-
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
-
- if (strcmp(name, "match") == 0)
- print_match(expr, format & FMT_NUMERIC);
-
- expr = nft_rule_expr_iter_next(iter);
- }
- nft_rule_expr_iter_destroy(iter);
-
- return 0;
-}
-
-int print_target(const char *targname, const void *targinfo,
- size_t target_len, int format)
-{
- struct xtables_target *target;
- struct xt_entry_target *t;
-
- if (targname == NULL)
- return 0;
-
- t = calloc(1, sizeof(struct xt_entry_target) + target_len);
- if (t == NULL)
- return -ENOMEM;
-
- /* emulate struct xt_entry_target since ->print needs it */
- memcpy((void *)&t->data, targinfo, target_len);
-
- target = xtables_find_target(targname, XTF_TRY_LOAD);
- if (target) {
- if (target->print)
- /* FIXME missing first parameter */
- target->print(NULL, t, format & FMT_NUMERIC);
- } else if (target_len > 0)
- printf("[%ld bytes of unknown target data] ", target_len);
-
- free(t);
-
- return 0;
-}
-
void print_num(uint64_t number, unsigned int format)
{
if (format & FMT_KILOMEGAGIGA) {
@@ -694,6 +560,24 @@ void print_firewall_details(const struct iptables_command_state *cs,
}
}
+void print_matches_and_target(struct iptables_command_state *cs,
+ unsigned int format)
+{
+ struct xtables_rule_match *matchp;
+
+ for (matchp = cs->matches; matchp; matchp = matchp->next) {
+ if (matchp->match->print != NULL)
+ matchp->match->print(NULL, matchp->match->m,
+ format & FMT_NUMERIC);
+ }
+
+ if (cs->target != NULL) {
+ if (cs->target->print != NULL)
+ cs->target->print(NULL, cs->target->t,
+ format & FMT_NUMERIC);
+ }
+}
+
static enum nft_instruction nft_ipt_counters_instructions[] = {
NFT_INSTRUCTION_COUNTER,
NFT_INSTRUCTION_MAX,
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 176abed..20e49bd 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -84,8 +84,6 @@ bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
void parse_meta(struct nft_rule_expr *e, uint8_t key, char *iniface,
unsigned char *iniface_mask, char *outiface,
unsigned char *outiface_mask, uint8_t *invflags);
-const char *nft_parse_target(struct nft_rule *r, const void **targinfo,
- size_t *target_len);
void print_proto(uint16_t proto, int invert);
void get_expr_cmp_data(struct nft_rule_expr *e,
void *data, size_t dlen, bool *inv);
@@ -93,15 +91,14 @@ void get_cmp_data(struct nft_rule_expr_iter *iter,
void *data, size_t dlen, bool *inv);
void nft_rule_to_iptables_command_state(struct nft_rule *r,
struct iptables_command_state *cs);
-int print_matches(struct nft_rule *r, int format);
-int print_target(const char *targname, const void *targinfo,
- size_t target_len, int format);
void print_num(uint64_t number, unsigned int format);
void print_firewall_details(const struct iptables_command_state *cs,
const char *targname, uint8_t flags,
uint8_t invflags, uint8_t proto,
const char *iniface, const char *outiface,
unsigned int num, unsigned int format);
+void print_matches_and_target(struct iptables_command_state *cs,
+ unsigned int format);
int nft_initiate_translation_tree(void);
struct nft_family_ops *nft_family_ops_lookup(int family);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 12/16] nft: Refactor rule deletion so it compares both cs structure
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (10 preceding siblings ...)
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 13:31 ` 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
` (3 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Now that we parse properly, in one place and at once, the rule back into a
command structure, it's now easier to compare the rule from that command
structure when deleting.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 195 +++++++++++----------------------------------------------
1 file changed, 35 insertions(+), 160 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 7171752..2cd2f77 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1672,188 +1672,63 @@ next:
return 0;
}
-static int matches_howmany(struct xtables_rule_match *matches)
-{
- struct xtables_rule_match *matchp;
- int matches_ctr = 0;
-
- for (matchp = matches; matchp; matchp = matchp->next)
- matches_ctr++;
-
- return matches_ctr;
-}
-
static bool
-__find_match(struct nft_rule_expr *expr, struct xtables_rule_match *matches)
+compare_matches(struct xtables_rule_match *matches_1,
+ struct xtables_rule_match *matches_2)
{
- const char *matchname = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
- /* Netlink aligns this match info, don't trust this length variable */
- const char *data = nft_rule_expr_get_str(expr, NFT_EXPR_MT_INFO);
- struct xtables_rule_match *matchp;
- bool found = false;
+ struct xtables_rule_match *mp_1;
+ struct xtables_rule_match *mp_2;
- for (matchp = matches; matchp; matchp = matchp->next) {
- struct xt_entry_match *m = matchp->match->m;
+ for (mp_1 = matches_1, mp_2 = matches_2;
+ mp_1 && mp_2; mp_1 = mp_1->next, mp_2 = mp_2->next) {
+ struct xt_entry_match *m_1 = mp_1->match->m;
+ struct xt_entry_match *m_2 = mp_2->match->m;
- if (strcmp(m->u.user.name, matchname) != 0) {
+ if (strcmp(m_1->u.user.name, m_2->u.user.name) != 0) {
DEBUGP("mismatching match name\n");
- continue;
+ return false;
}
- if (memcmp(data, m->data, m->u.user.match_size - sizeof(*m)) != 0) {
- DEBUGP("mismatch match data\n");
- continue;
+ if (m_1->u.user.match_size != m_2->u.user.match_size) {
+ DEBUGP("mismatching match size\n");
+ return false;
}
- found = true;
- break;
- }
-
- return found;
-}
-
-static bool find_matches(struct xtables_rule_match *matches, struct nft_rule *r)
-{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- int kernel_matches = 0;
-
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return false;
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
-
- if (strcmp(name, "match") == 0) {
- if (!__find_match(expr, matches))
- return false;
-
- kernel_matches++;
+ if (memcmp(m_1->data, m_2->data,
+ m_1->u.user.match_size - sizeof(*m_1)) != 0) {
+ DEBUGP("mismatch match data\n");
+ return false;
}
- expr = nft_rule_expr_iter_next(iter);
}
- nft_rule_expr_iter_destroy(iter);
- /* same number of matches? */
- if (matches_howmany(matches) != kernel_matches)
- return false;
-
- return true;
-}
-
-static bool __find_target(struct nft_rule_expr *expr, struct xt_entry_target *t)
-{
- size_t len;
- const char *tgname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
- /* Netlink aligns this target info, don't trust this length variable */
- const char *data = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
-
- if (strcmp(t->u.user.name, tgname) != 0) {
- DEBUGP("mismatching target name\n");
+ /* Both cursor should be NULL */
+ if (mp_1 != mp_2) {
+ DEBUGP("mismatch matches amount\n");
return false;
}
- if (memcmp(data, t->data, t->u.user.target_size - sizeof(*t)) != 0)
- return false;
-
return true;
}
-static int targets_howmany(struct xtables_target *target)
-{
- return target != NULL ? 1 : 0;
-}
-
static bool
-find_target(struct xtables_target *target, struct nft_rule *r)
+compare_targets(struct xtables_target *target_1,
+ struct xtables_target *target_2)
{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- int kernel_targets = 0;
-
- /* Special case: we use native immediate expressions to emulated
- * standard targets. Also, we don't want to crash with no targets.
- */
- if (target == NULL || strcmp(target->name, "standard") == 0)
+ if (target_1 == NULL && target_2 == NULL)
return true;
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
+ if ((target_1 == NULL && target_2 != NULL) ||
+ (target_1 != NULL && target_2 == NULL))
return false;
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
-
- if (strcmp(name, "target") == 0) {
- /* we may support several targets in the future */
- if (!__find_target(expr, target->t))
- return false;
-
- kernel_targets++;
- }
- expr = nft_rule_expr_iter_next(iter);
- }
- nft_rule_expr_iter_destroy(iter);
-
- /* same number of targets? */
- if (targets_howmany(target) != kernel_targets) {
- DEBUGP("kernel targets is %d but we passed %d\n",
- kernel_targets, targets_howmany(target));
+ if (strcmp(target_1->t->u.user.name, target_2->t->u.user.name) != 0)
return false;
- }
- return true;
-}
-
-static bool
-find_immediate(struct nft_rule *r, const char *jumpto)
-{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
-
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
+ if (memcmp(target_1->t->data, target_2->t->data,
+ target_1->t->u.user.target_size -
+ sizeof(*target_1->t)) != 0)
return false;
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
-
- if (strcmp(name, "immediate") == 0) {
- int verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
- const char *verdict_name = NULL;
-
- /* No target specified but immediate shows up, this
- * is not the rule we are looking for.
- */
- if (strlen(jumpto) == 0)
- return false;
-
- switch(verdict) {
- case NF_ACCEPT:
- verdict_name = "ACCEPT";
- break;
- case NF_DROP:
- verdict_name = "DROP";
- break;
- case NFT_RETURN:
- verdict_name = "RETURN";
- break;
- }
-
- /* Standard target? */
- if (verdict_name && strcmp(jumpto, verdict_name) != 0)
- return false;
- }
- expr = nft_rule_expr_iter_next(iter);
- }
- nft_rule_expr_iter_destroy(iter);
-
return true;
}
@@ -1932,18 +1807,18 @@ nft_rule_find(struct nft_rule_list *list, const char *chain, const char *table,
if (!ops->is_same(cs, &this))
goto next;
- if (!find_matches(cs->matches, r)) {
- DEBUGP("matches not found\n");
+ if (!compare_matches(cs->matches, this.matches)) {
+ DEBUGP("Different matches\n");
goto next;
}
- if (!find_target(cs->target, r)) {
- DEBUGP("target not found\n");
+ if (!compare_targets(cs->target, this.target)) {
+ DEBUGP("Different target\n");
goto next;
}
- if (!find_immediate(r, cs->jumpto)) {
- DEBUGP("immediate not found\n");
+ if (strcmp(cs->jumpto, this.jumpto) != 0) {
+ DEBUGP("Different verdict\n");
goto next;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 13/16] xtables: nft: Complete refactoring on how rules are saved
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (11 preceding siblings ...)
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 ` Tomasz Bursztyka
2013-08-09 13:31 ` [iptables-nftables RFC v3 PATCH 14/16] xtables: Support pure nft expressions for DNAT extension Tomasz Bursztyka
` (2 subsequent siblings)
15 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Now that we parse properly, in one place and at once, the rule back into a
command structure, it's now easier to save the rule from that command
structure.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft-ipv4.c | 122 ++++++--------------
iptables/nft-ipv6.c | 72 +++++-------
iptables/nft-shared.c | 72 ++++++++++--
iptables/nft-shared.h | 13 ++-
iptables/nft.c | 283 +++++++---------------------------------------
iptables/nft.h | 4 +-
iptables/xtables-events.c | 21 ++--
7 files changed, 184 insertions(+), 403 deletions(-)
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 02b52df..a20d2e2 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -97,50 +97,6 @@ static void get_frag_from_expr(struct nft_rule_expr *e, bool *inv)
*inv = false;
}
-static void get_frag(struct nft_rule_expr_iter *iter, bool *inv)
-{
- struct nft_rule_expr *e;
- const char *name;
- uint8_t op;
-
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
- /* we assume correct mask and xor */
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "bitwise") != 0) {
- DEBUGP("skipping no bitwise after payload\n");
- return;
- }
-
- /* Now check for cmp */
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
- /* we assume correct data */
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after payload\n");
- return;
- }
-
- op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP);
- if (op == NFT_CMP_EQ)
- *inv = true;
- else
- *inv = false;
-}
-
-static void print_frag(bool inv)
-{
- if (inv)
- printf("! -f ");
- else
- printf("-f ");
-}
-
static const char *mask_to_str(uint32_t mask)
{
static char mask_str[sizeof("255.255.255.255")];
@@ -167,50 +123,6 @@ static const char *mask_to_str(uint32_t mask)
return mask_str;
}
-static void nft_ipv4_print_payload(struct nft_rule_expr *e,
- struct nft_rule_expr_iter *iter)
-{
- uint32_t offset;
- bool inv;
-
- offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
-
- switch(offset) {
- struct in_addr addr;
- uint8_t proto;
-
- case offsetof(struct iphdr, saddr):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
- if (inv)
- printf("! -s %s/%s ", inet_ntoa(addr),
- mask_to_str(0xffffffff));
- else
- printf("-s %s/%s ", inet_ntoa(addr),
- mask_to_str(0xffffffff));
- break;
- case offsetof(struct iphdr, daddr):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
- if (inv)
- printf("! -d %s/%s ", inet_ntoa(addr),
- mask_to_str(0xffffffff));
- else
- printf("-d %s/%s ", inet_ntoa(addr),
- mask_to_str(0xffffffff));
- break;
- case offsetof(struct iphdr, protocol):
- get_cmp_data(iter, &proto, sizeof(proto), &inv);
- print_proto(proto, inv);
- break;
- case offsetof(struct iphdr, frag_off):
- get_frag(iter, &inv);
- print_frag(inv);
- break;
- default:
- DEBUGP("unknown payload offset %d\n", offset);
- break;
- }
-}
-
static void nft_ipv4_parse_meta(struct nft_rule_expr *e, uint8_t key,
struct iptables_command_state *cs)
{
@@ -325,6 +237,38 @@ static void nft_ipv4_print_firewall(struct nft_rule *r, unsigned int num,
fputc('\n', stdout);
}
+static void save_ipv4_addr(char letter, const struct in_addr *addr,
+ uint32_t mask, int invert)
+{
+ if (!mask && !invert && !addr->s_addr)
+ return;
+
+ printf("%s-%c %s/%s ", invert ? "! " : "", letter,
+ inet_ntoa(*addr), mask_to_str(mask));
+}
+
+static uint8_t nft_ipv4_save_firewall(const struct iptables_command_state *cs,
+ unsigned int format)
+{
+ save_firewall_details(cs, cs->fw.ip.invflags, cs->fw.ip.proto,
+ cs->fw.ip.iniface, cs->fw.ip.iniface_mask,
+ cs->fw.ip.outiface, cs->fw.ip.outiface_mask,
+ format);
+
+ if (cs->fw.ip.flags & IPT_F_FRAG) {
+ if (cs->fw.ip.invflags & IPT_INV_FRAG)
+ printf("! ");
+ printf("-f ");
+ }
+
+ save_ipv4_addr('s', &cs->fw.ip.src, cs->fw.ip.smsk.s_addr,
+ cs->fw.ip.invflags & IPT_INV_SRCIP);
+ save_ipv4_addr('d', &cs->fw.ip.dst, cs->fw.ip.dmsk.s_addr,
+ cs->fw.ip.invflags & IPT_INV_DSTIP);
+
+ return cs->fw.ip.flags;
+}
+
static void nft_ipv4_post_parse(int command,
struct iptables_command_state *cs,
struct xtables_args *args)
@@ -374,10 +318,10 @@ static void nft_ipv4_post_parse(int command,
struct nft_family_ops nft_family_ops_ipv4 = {
.add = nft_ipv4_add,
.is_same = nft_ipv4_is_same,
- .print_payload = nft_ipv4_print_payload,
.parse_meta = nft_ipv4_parse_meta,
.parse_payload = nft_ipv4_parse_payload,
.parse_immediate = nft_ipv4_parse_immediate,
.print_firewall = nft_ipv4_print_firewall,
+ .save_firewall = nft_ipv4_save_firewall,
.post_parse = nft_ipv4_post_parse,
};
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 15c37f6..aa3f6ab 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -69,48 +69,6 @@ static bool nft_ipv6_is_same(const struct iptables_command_state *a,
b->fw6.ipv6.outiface_mask);
}
-static void nft_ipv6_print_payload(struct nft_rule_expr *e,
- struct nft_rule_expr_iter *iter)
-{
- uint32_t offset;
- bool inv;
-
- offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
-
- switch (offset) {
- char addr_str[INET6_ADDRSTRLEN];
- struct in6_addr addr;
- uint8_t proto;
- case offsetof(struct ip6_hdr, ip6_src):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
- inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
-
- if (inv)
- printf("! -s %s ", addr_str);
- else
- printf("-s %s ", addr_str);
-
- break;
- case offsetof(struct ip6_hdr, ip6_dst):
- get_cmp_data(iter, &addr, sizeof(addr), &inv);
- inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
-
- if (inv)
- printf("! -d %s ", addr_str);
- else
- printf("-d %s ", addr_str);
-
- break;
- case offsetof(struct ip6_hdr, ip6_nxt):
- get_cmp_data(iter, &proto, sizeof(proto), &inv);
- print_proto(proto, inv);
- break;
- default:
- DEBUGP("unknown payload offset %d\n", offset);
- break;
- }
-}
-
static void nft_ipv6_parse_meta(struct nft_rule_expr *e, uint8_t key,
struct iptables_command_state *cs)
{
@@ -223,6 +181,34 @@ static void nft_ipv6_print_firewall(struct nft_rule *r, unsigned int num,
fputc('\n', stdout);
}
+static void save_ipv6_addr(char letter, const struct in6_addr *addr,
+ int invert)
+{
+ char addr_str[INET6_ADDRSTRLEN];
+
+ if (!invert && !IN6_IS_ADDR_UNSPECIFIED(addr))
+ return;
+
+ inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
+ printf("%s-%c %s ", invert ? "! " : "", letter, addr_str);
+}
+
+static uint8_t nft_ipv6_save_firewall(const struct iptables_command_state *cs,
+ unsigned int format)
+{
+ save_firewall_details(cs, cs->fw6.ipv6.invflags, cs->fw6.ipv6.proto,
+ cs->fw6.ipv6.iniface, cs->fw6.ipv6.iniface_mask,
+ cs->fw6.ipv6.outiface, cs->fw6.ipv6.outiface_mask,
+ format);
+
+ save_ipv6_addr('s', &cs->fw6.ipv6.src,
+ cs->fw6.ipv6.invflags & IPT_INV_SRCIP);
+ save_ipv6_addr('d', &cs->fw6.ipv6.dst,
+ cs->fw6.ipv6.invflags & IPT_INV_DSTIP);
+
+ return cs->fw6.ipv6.flags;
+}
+
/* These are invalid numbers as upper layer protocol */
static int is_exthdr(uint16_t proto)
{
@@ -292,10 +278,10 @@ static void nft_ipv6_post_parse(int command, struct iptables_command_state *cs,
struct nft_family_ops nft_family_ops_ipv6 = {
.add = nft_ipv6_add,
.is_same = nft_ipv6_is_same,
- .print_payload = nft_ipv6_print_payload,
.parse_meta = nft_ipv6_parse_meta,
.parse_payload = nft_ipv6_parse_payload,
.parse_immediate = nft_ipv6_parse_immediate,
.print_firewall = nft_ipv6_print_firewall,
+ .save_firewall = nft_ipv6_save_firewall,
.post_parse = nft_ipv6_post_parse,
};
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 4eba145..c9aeef4 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -320,18 +320,6 @@ void get_expr_cmp_data(struct nft_rule_expr *e,
*inv = false;
}
-void get_cmp_data(struct nft_rule_expr_iter *iter,
- void *data, size_t dlen, bool *inv)
-{
- struct nft_rule_expr *e;
-
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
- get_expr_cmp_data(e, data, dlen, inv);
-}
-
static int
nft_parse_counters(struct nft_trans_rule_context *rule_ctx,
struct nft_trans_instruction_context *first,
@@ -560,6 +548,66 @@ void print_firewall_details(const struct iptables_command_state *cs,
}
}
+static void
+print_iface(char letter, const char *iface, const unsigned char *mask,
+ int invert)
+{
+ unsigned int i;
+
+ if (mask[0] == 0)
+ return;
+
+ printf("%s-%c ", invert ? "! " : "", letter);
+
+ for (i = 0; i < IFNAMSIZ; i++) {
+ if (mask[i] != 0) {
+ if (iface[i] != '\0')
+ printf("%c", iface[i]);
+ } else {
+ if (iface[i-1] != '\0')
+ printf("+");
+ break;
+ }
+ }
+
+ printf(" ");
+}
+
+void save_firewall_details(const struct iptables_command_state *cs,
+ uint8_t invflags, uint16_t proto,
+ const char *iniface,
+ unsigned const char *iniface_mask,
+ const char *outiface,
+ unsigned const char *outiface_mask,
+ unsigned int format)
+{
+ if (!(format & FMT_NOCOUNTS)) {
+ printf("-c ");
+ print_num(cs->counters.pcnt, format);
+ print_num(cs->counters.bcnt, format);
+ }
+
+ if (iniface != NULL)
+ print_iface('i', iniface, iniface_mask,
+ invflags & IPT_INV_VIA_IN);
+
+ if (outiface != NULL)
+ print_iface('o', outiface, outiface_mask,
+ invflags & IPT_INV_VIA_OUT);
+
+ if (proto > 0) {
+ const struct protoent *pent = getprotobynumber(proto);
+
+ if (invflags & XT_INV_PROTO)
+ printf("! ");
+
+ if (pent)
+ printf("-p %s ", pent->p_name);
+ else
+ printf("-p %u ", proto);
+ }
+}
+
void print_matches_and_target(struct iptables_command_state *cs,
unsigned int format)
{
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 20e49bd..da38cf9 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -44,8 +44,6 @@ struct nft_family_ops {
int (*add)(struct nft_rule *r, struct iptables_command_state *cs);
bool (*is_same)(const struct iptables_command_state *a,
const struct iptables_command_state *b);
- void (*print_payload)(struct nft_rule_expr *e,
- struct nft_rule_expr_iter *iter);
void (*parse_meta)(struct nft_rule_expr *e, uint8_t key,
struct iptables_command_state *cs);
void (*parse_payload)(struct nft_rule_expr *e_1,
@@ -55,6 +53,8 @@ struct nft_family_ops {
void (*parse_immediate)(struct iptables_command_state *cs);
void (*print_firewall)(struct nft_rule *r, unsigned int num,
unsigned int format);
+ uint8_t (*save_firewall)(const struct iptables_command_state *cs,
+ unsigned int format);
void (*post_parse)(int command, struct iptables_command_state *cs,
struct xtables_args *args);
};
@@ -87,8 +87,6 @@ void parse_meta(struct nft_rule_expr *e, uint8_t key, char *iniface,
void print_proto(uint16_t proto, int invert);
void get_expr_cmp_data(struct nft_rule_expr *e,
void *data, size_t dlen, bool *inv);
-void get_cmp_data(struct nft_rule_expr_iter *iter,
- void *data, size_t dlen, bool *inv);
void nft_rule_to_iptables_command_state(struct nft_rule *r,
struct iptables_command_state *cs);
void print_num(uint64_t number, unsigned int format);
@@ -97,6 +95,13 @@ void print_firewall_details(const struct iptables_command_state *cs,
uint8_t invflags, uint8_t proto,
const char *iniface, const char *outiface,
unsigned int num, unsigned int format);
+void save_firewall_details(const struct iptables_command_state *cs,
+ uint8_t invflags, uint16_t proto,
+ const char *iniface,
+ unsigned const char *iniface_mask,
+ const char *outiface,
+ unsigned const char *outiface_mask,
+ unsigned int format);
void print_matches_and_target(struct iptables_command_state *cs,
unsigned int format);
int nft_initiate_translation_tree(void);
diff --git a/iptables/nft.c b/iptables/nft.c
index 2cd2f77..7ec3762 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -793,224 +793,27 @@ err:
return ret == 0 ? 1 : 0;
}
-static void nft_match_save(struct nft_rule_expr *expr)
-{
- const char *name;
- const struct xtables_match *match;
- struct xt_entry_match *emu;
- const void *mtinfo;
- size_t len;
-
- name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
-
- match = xtables_find_match(name, XTF_TRY_LOAD, NULL);
- if (match == NULL)
- return;
-
- mtinfo = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
- if (mtinfo == NULL)
- return;
-
- emu = calloc(1, sizeof(struct xt_entry_match) + len);
- if (emu == NULL)
- return;
-
- memcpy(&emu->data, mtinfo, len);
-
- if (match->alias)
- printf("-m %s", match->alias(emu));
- else
- printf("-m %s", match->name);
-
- /* FIXME missing parameter */
- if (match->save)
- match->save(NULL, emu);
-
- printf(" ");
-
- free(emu);
-}
-
-static void nft_target_save(struct nft_rule_expr *expr)
-{
- const char *name;
- const struct xtables_target *target;
- struct xt_entry_target *emu;
- const void *tginfo;
- size_t len;
-
- name = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
-
- /* Standard target not supported, we use native immediate expression */
- if (strcmp(name, "") == 0) {
- printf("ERROR: standard target seen, should not happen\n");
- return;
- }
-
- target = xtables_find_target(name, XTF_TRY_LOAD);
- if (target == NULL)
- return;
-
- tginfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
- if (tginfo == NULL)
- return;
-
- emu = calloc(1, sizeof(struct xt_entry_match) + len);
- if (emu == NULL)
- return;
-
- memcpy(emu->data, tginfo, len);
-
- if (target->alias)
- printf("-j %s", target->alias(emu));
- else
- printf("-j %s", target->name);
-
- /* FIXME missing parameter */
- if (target->save)
- target->save(NULL, emu);
-
- free(emu);
-}
-
-static void nft_immediate_save(struct nft_rule_expr *expr)
-{
- uint32_t verdict;
-
- verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
-
- switch(verdict) {
- case NF_ACCEPT:
- printf("-j ACCEPT");
- break;
- case NF_DROP:
- printf("-j DROP");
- break;
- case NFT_RETURN:
- printf("-j RETURN");
- break;
- case NFT_GOTO:
- printf("-g %s",
- nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
- break;
- case NFT_JUMP:
- printf("-j %s",
- nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
- break;
- }
-}
-
-static void
-nft_print_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
+void
+nft_rule_print_save(const struct iptables_command_state *cs,
+ struct nft_rule *r, enum nft_rule_print type,
+ unsigned int format)
{
- uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
- uint32_t value;
- const char *name;
- char ifname[IFNAMSIZ];
- const char *ifname_ptr;
- size_t len;
-
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- /* meta should be followed by cmp */
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
- return;
- }
-
- switch(key) {
- case NFT_META_IIF:
- value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
- if_indextoname(value, ifname);
-
- switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
- case NFT_CMP_EQ:
- printf("-i %s ", ifname);
- break;
- case NFT_CMP_NEQ:
- printf("! -i %s ", ifname);
- break;
- }
- break;
- case NFT_META_OIF:
- value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
- if_indextoname(value, ifname);
-
- switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
- case NFT_CMP_EQ:
- printf("-o %s ", ifname);
- break;
- case NFT_CMP_NEQ:
- printf("! -o %s ", ifname);
- break;
- }
- break;
- case NFT_META_IIFNAME:
- ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
- memcpy(ifname, ifname_ptr, len);
- ifname[len] = '\0';
-
- /* if this is zero, then assume this is a interface mask */
- if (if_nametoindex(ifname) == 0) {
- ifname[len] = '+';
- ifname[len+1] = '\0';
- }
+ const char *chain = nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
+ int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
+ struct xtables_rule_match *matchp;
+ struct nft_family_ops *ops;
+ int ip_flags = 0;
- switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
- case NFT_CMP_EQ:
- printf("-i %s ", ifname);
- break;
- case NFT_CMP_NEQ:
- printf("! -i %s ", ifname);
- break;
- }
+ switch(family) {
+ case AF_INET:
+ printf("-4 ");
break;
- case NFT_META_OIFNAME:
- ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
- memcpy(ifname, ifname_ptr, len);
- ifname[len] = '\0';
-
- /* if this is zero, then assume this is a interface mask */
- if (if_nametoindex(ifname) == 0) {
- ifname[len] = '+';
- ifname[len+1] = '\0';
- }
-
- switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
- case NFT_CMP_EQ:
- printf("-o %s ", ifname);
- break;
- case NFT_CMP_NEQ:
- printf("! -o %s ", ifname);
- break;
- }
+ case AF_INET6:
+ printf("-6 ");
break;
default:
- DEBUGP("unknown meta key %d\n", key);
break;
}
-}
-
-static void
-nft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- bool counters)
-{
- if (counters) {
- printf("-c %"PRIu64" %"PRIu64" ",
- nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS),
- nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES));
- }
-}
-
-void
-nft_rule_print_save(struct nft_rule *r, enum nft_rule_print type, bool counters)
-{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- const char *chain = nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
/* print chain name */
switch(type) {
@@ -1022,33 +825,24 @@ nft_rule_print_save(struct nft_rule *r, enum nft_rule_print type, bool counters)
break;
}
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return;
+ ops = nft_family_ops_lookup(family);
+ ip_flags = ops->save_firewall(cs, format);
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
+ for (matchp = cs->matches; matchp; matchp = matchp->next) {
+ printf("-m %s", matchp->match->name);
+ if (matchp->match->save != NULL)
+ matchp->match->save(NULL, matchp->match->m);
+ printf(" ");
+ }
- if (strcmp(name, "counter") == 0) {
- nft_print_counters(expr, iter, counters);
- } else if (strcmp(name, "payload") == 0) {
- struct nft_family_ops *ops = nft_family_ops_lookup(
- nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY));
- ops->print_payload(expr, iter);
- } else if (strcmp(name, "meta") == 0) {
- nft_print_meta(expr, iter);
- } else if (strcmp(name, "match") == 0) {
- nft_match_save(expr);
- } else if (strcmp(name, "target") == 0) {
- nft_target_save(expr);
- } else if (strcmp(name, "immediate") == 0) {
- nft_immediate_save(expr);
- }
+ if (cs->target != NULL) {
+ printf("-j %s", cs->jumpto);
- expr = nft_rule_expr_iter_next(iter);
- }
+ if (cs->target->save != NULL)
+ cs->target->save(NULL, cs->target->t);
+ } else if (strlen(cs->jumpto) > 0)
+ printf("-%c %s", ip_flags & IPT_F_GOTO ? 'g' : 'j',
+ cs->jumpto);
printf("\n");
}
@@ -1230,11 +1024,15 @@ int nft_rule_save(struct nft_handle *h, const char *table, bool counters)
while (r != NULL) {
const char *rule_table =
nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
+ struct iptables_command_state cs = {};
if (strcmp(table, rule_table) != 0)
goto next;
- nft_rule_print_save(r, NFT_RULE_APPEND, counters);
+ nft_rule_to_iptables_command_state(r, &cs);
+
+ nft_rule_print_save(&cs, r, NFT_RULE_APPEND,
+ counters ? 0 : FMT_NOCOUNTS);
next:
r = nft_rule_list_iter_next(iter);
@@ -1797,13 +1595,12 @@ nft_rule_find(struct nft_rule_list *list, const char *chain, const char *table,
break;
} else {
/* Delete by matching rule case */
+ nft_rule_to_iptables_command_state(r, &this);
+
DEBUGP("comparing with... ");
#ifdef DEBUG_DEL
- nft_rule_print_save(r, NFT_RULE_APPEND, 0);
+ nft_rule_print_save(&this, r, NFT_RULE_APPEND, 0);
#endif
-
- nft_rule_to_iptables_command_state(r, &this);
-
if (!ops->is_same(cs, &this))
goto next;
@@ -2210,7 +2007,11 @@ err:
static void
list_save(struct nft_rule *r, unsigned int num, unsigned int format)
{
- nft_rule_print_save(r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
+ struct iptables_command_state cs = {};
+
+ nft_rule_to_iptables_command_state(r, &cs);
+
+ nft_rule_print_save(&cs, r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
}
static int
diff --git a/iptables/nft.h b/iptables/nft.h
index f3317c9..006c031 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -87,7 +87,9 @@ enum nft_rule_print {
NFT_RULE_DEL,
};
-void nft_rule_print_save(struct nft_rule *r, enum nft_rule_print type, bool counters);
+void nft_rule_print_save(const struct iptables_command_state *cs,
+ struct nft_rule *r, enum nft_rule_print type,
+ unsigned int format);
/*
* global commit and abort
diff --git a/iptables/xtables-events.c b/iptables/xtables-events.c
index 64ae972..220a28e 100644
--- a/iptables/xtables-events.c
+++ b/iptables/xtables-events.c
@@ -58,6 +58,7 @@ static bool counters;
static int rule_cb(const struct nlmsghdr *nlh, int type)
{
+ struct iptables_command_state cs = {};
struct nft_rule *r;
r = nft_rule_alloc();
@@ -71,20 +72,12 @@ static int rule_cb(const struct nlmsghdr *nlh, int type)
goto err_free;
}
- switch(nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY)) {
- case AF_INET:
- printf("-4 ");
- break;
- case AF_INET6:
- printf("-6 ");
- break;
- default:
- break;
- }
+ nft_rule_to_iptables_command_state(r, &cs);
- nft_rule_print_save(r, type == NFT_MSG_NEWRULE ? NFT_RULE_APPEND :
- NFT_RULE_DEL,
- counters);
+ nft_rule_print_save(&cs, r,
+ type == NFT_MSG_NEWRULE ?
+ NFT_RULE_APPEND : NFT_RULE_DEL,
+ counters ? 0 : FMT_NOCOUNTS);
err_free:
nft_rule_free(r);
err:
@@ -195,6 +188,8 @@ int xtables_events_main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ nft_initiate_translation_tree();
+
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
while (ret > 0) {
ret = mnl_cb_run(buf, ret, 0, 0, events_cb, NULL);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 14/16] xtables: Support pure nft expressions for DNAT extension
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (12 preceding siblings ...)
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 ` Tomasz Bursztyka
2013-08-09 21:56 ` Pablo Neira Ayuso
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 13:31 ` [iptables-nftables RFC v3 PATCH 16/16] xtables: Support -Z options for a given rule number Tomasz Bursztyka
15 siblings, 1 reply; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
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;
+ }
+
+ 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;
+ }
+
+ return 0;
+}
+
+static enum nft_instruction xt_dnat_instructions_1[] = {
+ NFT_INSTRUCTION_IMMEDIATE, NFT_INSTRUCTION_NAT,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction xt_dnat_1 = {
+ .instructions = xt_dnat_instructions_1,
+ .function = DNAT_parse_nft,
+};
+
+static enum nft_instruction xt_dnat_instructions_2[] = {
+ NFT_INSTRUCTION_IMMEDIATE, NFT_INSTRUCTION_IMMEDIATE,
+ NFT_INSTRUCTION_NAT,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction xt_dnat_2 = {
+ .instructions = xt_dnat_instructions_2,
+ .function = DNAT_parse_nft,
+};
+
+static enum nft_instruction xt_dnat_instructions_3[] = {
+ NFT_INSTRUCTION_IMMEDIATE, NFT_INSTRUCTION_IMMEDIATE,
+ NFT_INSTRUCTION_IMMEDIATE, NFT_INSTRUCTION_NAT,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction xt_dnat_3 = {
+ .instructions = xt_dnat_instructions_3,
+ .function = DNAT_parse_nft,
+};
+
+static enum nft_instruction xt_dnat_instructions_4[] = {
+ NFT_INSTRUCTION_IMMEDIATE, NFT_INSTRUCTION_IMMEDIATE,
+ NFT_INSTRUCTION_IMMEDIATE, NFT_INSTRUCTION_IMMEDIATE,
+ NFT_INSTRUCTION_NAT,
+ NFT_INSTRUCTION_MAX,
+};
+
+static struct nft_trans_instruction xt_dnat_4 = {
+ .instructions = xt_dnat_instructions_4,
+ .function = DNAT_parse_nft,
+};
+
+static int DNAT_register_nft_instructions(struct nft_trans_instruction_tree *tree)
+{
+ nft_trans_add_instruction(tree, &xt_dnat_1);
+ nft_trans_add_instruction(tree, &xt_dnat_2);
+ nft_trans_add_instruction(tree, &xt_dnat_3);
+ nft_trans_add_instruction(tree, &xt_dnat_4);
+
+ return 0;
+}
+
static struct xtables_target dnat_tg_reg = {
.name = "DNAT",
.version = XTABLES_VERSION,
@@ -254,6 +473,8 @@ static struct xtables_target dnat_tg_reg = {
.print = DNAT_print,
.save = DNAT_save,
.x6_options = DNAT_opts,
+ .to_nft = DNAT_to_nft,
+ .register_nft_instructions = DNAT_register_nft_instructions,
};
void _init(void)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 15/16] nft: Add a function to reset the counters of an existing rule
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (13 preceding siblings ...)
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 13:31 ` 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
15 siblings, 1 reply; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Now that we parse properly, in one place and at once, the rule back into a
command structure, it's now easier to reset its counters from that command
structure which we can pass again to nft_rule_append. (Thus the rule will
be replaced since we provide it's handle.)
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 35 +++++++++++++++++++++++++++++++++++
iptables/nft.h | 1 +
2 files changed, 36 insertions(+)
diff --git a/iptables/nft.c b/iptables/nft.c
index 7ec3762..ad999a0 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2109,6 +2109,41 @@ err:
return ret;
}
+int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
+ const char *table, int rulenum)
+{
+ struct iptables_command_state cs = {};
+ struct nft_rule_list *list;
+ struct nft_rule *r;
+ int ret = 0;
+
+ nft_fn = nft_rule_delete;
+
+ list = nft_rule_list_create(h);
+ if (list == NULL)
+ return 0;
+
+ r = nft_rule_find(list, chain, table, NULL, rulenum);
+ if (r == NULL) {
+ errno = ENOENT;
+ ret = 1;
+
+ goto error;
+ }
+
+ nft_rule_to_iptables_command_state(r, &cs);
+
+ cs.counters.pcnt = cs.counters.bcnt = 0;
+
+ ret = nft_rule_append(h, chain, table, &cs,
+ nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE), false);
+
+error:
+ nft_rule_list_destroy(list);
+
+ return ret;
+}
+
static int nft_action(struct nft_handle *h, int type)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
diff --git a/iptables/nft.h b/iptables/nft.h
index 006c031..fe1b9c8 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -81,6 +81,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, in
int nft_rule_list_save(struct nft_handle *h, const char *chain, const char *table, int rulenum, int counters);
int nft_rule_save(struct nft_handle *h, const char *table, bool counters);
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table);
+int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char *table, int rulenum);
enum nft_rule_print {
NFT_RULE_APPEND,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [iptables-nftables RFC v3 PATCH 16/16] xtables: Support -Z options for a given rule number
2013-08-09 13:31 [iptables-nftables RFC v3 PATCH 00/16] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (14 preceding siblings ...)
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 13:31 ` Tomasz Bursztyka
2013-08-09 22:02 ` Pablo Neira Ayuso
15 siblings, 1 reply; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-09 13:31 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Tomasz Bursztyka
Support for such command:
xtbles-multi xtables -Z foo 4
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/xtables.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 946f04d..dae2500 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -1194,8 +1194,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
ret = nft_chain_zero_counters(h, chain, *table);
break;
case CMD_ZERO_NUM:
- /* FIXME */
-// ret = iptc_zero_counter(chain, rulenum, *handle);
+ ret = nft_rule_zero_counters(h, chain, *table, rulenum - 1);
break;
case CMD_LIST:
case CMD_LIST|CMD_ZERO:
@@ -1208,9 +1207,9 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
cs.options&OPT_LINENUMBERS);
if (ret && (command & CMD_ZERO))
ret = nft_chain_zero_counters(h, chain, *table);
- /* FIXME */
-/* if (ret && (command & CMD_ZERO_NUM))
- ret = iptc_zero_counter(chain, rulenum, *handle); */
+ if (ret && (command & CMD_ZERO_NUM))
+ ret = nft_rule_zero_counters(h, chain,
+ *table, rulenum - 1);
break;
case CMD_LIST_RULES:
case CMD_LIST_RULES|CMD_ZERO:
@@ -1218,9 +1217,9 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
ret = list_rules(h, chain, *table, rulenum, cs.options&OPT_VERBOSE);
if (ret && (command & CMD_ZERO))
ret = nft_chain_zero_counters(h, chain, *table);
- /* FIXME */
-/* if (ret && (command & CMD_ZERO_NUM))
- ret = iptc_zero_counter(chain, rulenum, *handle); */
+ if (ret && (command & CMD_ZERO_NUM))
+ ret = nft_rule_zero_counters(h, chain,
+ *table, rulenum - 1);
break;
case CMD_NEW_CHAIN:
ret = nft_chain_user_add(h, chain, *table);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 04/16] nft: Integrate nft translator engine in current core
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
0 siblings, 1 reply; 28+ messages in thread
From: Pablo Neira Ayuso @ 2013-08-09 21:24 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
Hi Tomasz,
On Fri, Aug 09, 2013 at 04:31:18PM +0300, Tomasz Bursztyka wrote:
[...]
> +static int nft_parse_ip_addresses(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_to_cs_data *i2cs = user_data;
> + struct nft_rule_expr *e1, *e2;
> + struct nft_family_ops *ops;
> + uint32_t offset;
> +
> + e1 = nft_trans_instruction_context_get_expr(first);
> + if (!nft_rule_expr_is_set(e1, NFT_EXPR_PAYLOAD_OFFSET))
> + return -1;
> +
> + offset = nft_rule_expr_get_u32(e1, NFT_EXPR_PAYLOAD_OFFSET);
> + ops = nft_family_ops_lookup(i2cs->family);
> +
> + first = nft_trans_instruction_context_get_next(first);
> + e1 = nft_trans_instruction_context_get_expr(first);
> + e2 = nft_trans_instruction_context_get_expr(last);
> +
> + ops->parse_payload(e1, e2, i2cs->cs, offset);
> +
> + return 0;
> +}
> +
[...]
> +static struct nft_trans_instruction nft_ipt_io_ifs = {
> + .instructions = nft_ipt_io_ifs_instructions,
> + .function = nft_parse_io_ifs,
> +};
> +
> +static enum nft_instruction nft_ipt_ip_addr_instructions_1[] = {
> + NFT_INSTRUCTION_PAYLOAD, NFT_INSTRUCTION_CMP,
> + NFT_INSTRUCTION_MAX,
> +};
> +
> +static struct nft_trans_instruction nft_ipt_ip_addr_1 = {
> + .instructions = nft_ipt_ip_addr_instructions_1,
> + .function = nft_parse_ip_addresses,
> +};
> +
> +static enum nft_instruction nft_ipt_ip_addr_instructions_2[] = {
> + NFT_INSTRUCTION_PAYLOAD, NFT_INSTRUCTION_BITWISE, NFT_INSTRUCTION_CMP,
> + NFT_INSTRUCTION_MAX,
> +};
If I understood this correctly, your approach uses the array of
instructions above as keys to look up for the corresponding parser. In
that case, I'm afraid that this engine won't cover the complexity of
the payload instructions since we'll end up having *a lot* of matching
combinations that will overlap in your tree. You cannot resolve that
ambiguity problem of what parser needs to be invoked without looking
at other information that is contained in the instruction, eg. payload
base and offset.
Regards.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 11/16] nft: Refactor firewall printing so it reuses already parsed cs struct
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
0 siblings, 1 reply; 28+ messages in thread
From: Pablo Neira Ayuso @ 2013-08-09 21:51 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
On Fri, Aug 09, 2013 at 04:31:25PM +0300, Tomasz Bursztyka wrote:
> Now that we parse properly, in one place and at once, the rule back into
> a command structure, it's now easier to print the rule from that command
> structure.
I like patches from 11 to 13, that refactorization save us quite some
code and the result in one single parsing and we also work with the
command structure.
Please, can you send me these three patches in first place?
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 14/16] xtables: Support pure nft expressions for DNAT extension
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
2013-08-12 7:42 ` Tomasz Bursztyka
0 siblings, 1 reply; 28+ messages in thread
From: Pablo Neira Ayuso @ 2013-08-09 21:56 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
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.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 15/16] nft: Add a function to reset the counters of an existing rule
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
0 siblings, 0 replies; 28+ messages in thread
From: Pablo Neira Ayuso @ 2013-08-09 22:00 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
On Fri, Aug 09, 2013 at 04:31:29PM +0300, Tomasz Bursztyka wrote:
> Now that we parse properly, in one place and at once, the rule back into a
> command structure, it's now easier to reset its counters from that command
> structure which we can pass again to nft_rule_append. (Thus the rule will
> be replaced since we provide it's handle.)
I guess this patch could follow up after the refactorization patches
(11-13) as I don't see any obvious dependency with your translation
engine.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 16/16] xtables: Support -Z options for a given rule number
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
0 siblings, 1 reply; 28+ messages in thread
From: Pablo Neira Ayuso @ 2013-08-09 22:02 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
On Fri, Aug 09, 2013 at 04:31:30PM +0300, Tomasz Bursztyka wrote:
> Support for such command:
> xtbles-multi xtables -Z foo 4
If you add an interface, you also have to add the first client of that
new interface.
This should be collapsed with patch 15/16.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 04/16] nft: Integrate nft translator engine in current core
2013-08-09 21:24 ` Pablo Neira Ayuso
@ 2013-08-12 7:15 ` Tomasz Bursztyka
0 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-12 7:15 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Hi Pablo,
> If I understood this correctly, your approach uses the array of
> instructions above as keys to look up for the corresponding parser. In
> that case, I'm afraid that this engine won't cover the complexity of
> the payload instructions since we'll end up having*a lot* of matching
> combinations that will overlap in your tree. You cannot resolve that
> ambiguity problem of what parser needs to be invoked without looking
> at other information that is contained in the instruction, eg. payload
> base and offset.
It already handles overlapping patterns. I decided to go the simplest way:
- you can register as many parser you want for a pattern, of course.
- engine will try as many parser it has for a pattern as long as those
return -1, the one who returns 0 wins (engine tries then to continue on
next expressions, finding other patterns)
- engine follows longest pattern first: so if no parser as won on the
current pattern, engine will start to go backward. (it will try to match
shorter pattern)
Have a look at nft_trans_add_instruction(),
retrieve_nft_trans_instructions() and execute_relevant_instruction() for
insights.
Sure it's definitely not the most optimized but I believe it should be
sufficient for our concerns.
And anyway, the API is good enough so the engine itself can be
transparently improved if necessary.
Tomasz
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 14/16] xtables: Support pure nft expressions for DNAT extension
2013-08-09 21:56 ` Pablo Neira Ayuso
@ 2013-08-12 7:42 ` Tomasz Bursztyka
0 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-12 7:42 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Hi Pablo,
> 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.
I agree, SNAT will be 99% same code. So it would be nice to factorize
that somewhere.
Maybe some new xtables .c file for common stuff like that.
>> >+
>> >+ 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.
Ok thanks for the notice, I followed the way it's currently done in the
userspace extension, did not know that it's not supported in kernel.
Tomasz
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 16/16] xtables: Support -Z options for a given rule number
2013-08-09 22:02 ` Pablo Neira Ayuso
@ 2013-08-12 7:45 ` Tomasz Bursztyka
0 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-12 7:45 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Hi Pablo,
> If you add an interface, you also have to add the first client of that
> new interface.
>
> This should be collapsed with patch 15/16.
Ok
Tomasz
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 11/16] nft: Refactor firewall printing so it reuses already parsed cs struct
2013-08-09 21:51 ` Pablo Neira Ayuso
@ 2013-08-12 7:54 ` Tomasz Bursztyka
2013-08-12 9:30 ` Pablo Neira Ayuso
0 siblings, 1 reply; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-12 7:54 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Hi Pablo,
> I like patches from 11 to 13, that refactorization save us quite some
> code and the result in one single parsing and we also work with the
> command structure.
>
> Please, can you send me these three patches in first place?
Not impossible but means a big rebase of this patchset.
(it currently needs translation stuff, or then it would require some
work to handle target/matches properly as original code does not in
nft_rule_to_iptables_command_state, without solving pure-nft expressed
extensions of course)
Could you recheck in detail patches 3/16 and 4/16?
If there is no flaws in the translation engine, we might just go for it
at it is.
Thanks,
Tomasz
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 11/16] nft: Refactor firewall printing so it reuses already parsed cs struct
2013-08-12 7:54 ` Tomasz Bursztyka
@ 2013-08-12 9:30 ` Pablo Neira Ayuso
2013-08-12 10:54 ` Tomasz Bursztyka
0 siblings, 1 reply; 28+ messages in thread
From: Pablo Neira Ayuso @ 2013-08-12 9:30 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
Hi Tomasz,
On Mon, Aug 12, 2013 at 10:54:27AM +0300, Tomasz Bursztyka wrote:
> Hi Pablo,
>
> >I like patches from 11 to 13, that refactorization save us quite some
> >code and the result in one single parsing and we also work with the
> >command structure.
> >
> >Please, can you send me these three patches in first place?
>
> Not impossible but means a big rebase of this patchset.
> (it currently needs translation stuff, or then it would require some
> work to handle target/matches properly as original code does not in
> nft_rule_to_iptables_command_state, without solving pure-nft
> expressed extensions of course)
>
> Could you recheck in detail patches 3/16 and 4/16?
> If there is no flaws in the translation engine, we might just go for
> it at it is.
I'm not convinced that this approach is the way to go. In the payload
case, the number of instruction tuples will explode, and you will have
to iterate many times to find the corresponding parser.
I started a quick patch this weekend based on this, the initial idea
is the following:
1) Assuming we use a common path to translate rules from nft to xt in
nft_rule_to_iptables_command_state, that function invokes a parser
depending on the instruction:
+void nft_parse_nat(struct nft_parse_ctx *ctx, struct nft_rule_expr
*e,
+ struct nft_rule_expr_iter *iter, int family,
+ struct iptables_command_state *cs)
+{
+ int nat_type;
+ struct nf_nat_range range;
+ uint32_t reg;
+
+ nat_type = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_TYPE);
+
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN);
+ if (reg)
+ range.min_addr.ip = ctx->registers[reg];
+
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX);
+ if (reg) {
+ range.flags |= NF_NAT_RANGE_MAP_IPS;
+ range.max_addr.ip = ctx->registers[reg];
+ }
+
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_PROTO_MIN);
+ if (reg)
+ range.min_proto.all = ctx->registers[reg];
+
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_PROTO_MAX);
+ if (reg) {
+ range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+ range.max_proto.all = ctx->registers[reg];
+ }
+
+ nft_nat_dispatcher(nat_type, family, &range);
+}
2) Then, this parser generates a structure that contains what most NAT
extension need. The immediate parser stores the values in the
ctx->registers, so the NAT will find what it needs there.
The dispatcher is specific per instruction, so we can look up for the
corresponding xt extension base on some specific tuple, in this case,
the family and the nat type:
+static void nft_nat_dispatcher(enum nft_nat_types nat_type, int fa
+ struct nf_nat_range *range)
+{
+ struct nft_xt_nat *xt_nat;
+
+ list_for_each_entry(xt_nat, &nft_xt_nat_list, head) {
+ if (xt_nat->family == family &&
+ xt_nat->nat_type == nat_type) {
+ xt_nat->parse(range);
+ return;
+ }
+ }
+}
This is currently a list, but we could implement it using a hashtable
in the payload case. The xt_nat->parse function is defined in the
corresponding xt extension.
Anyway, I really think we have to start by converting nft to ipt
command state in one single patch, as your patches 11-13 do, we need
it for whatever approach we decide to follow. If you don't have time
to make that rebase, I'll try to find some spare time to work on it.
Let me know.
Regards.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [iptables-nftables RFC v3 PATCH 11/16] nft: Refactor firewall printing so it reuses already parsed cs struct
2013-08-12 9:30 ` Pablo Neira Ayuso
@ 2013-08-12 10:54 ` Tomasz Bursztyka
0 siblings, 0 replies; 28+ messages in thread
From: Tomasz Bursztyka @ 2013-08-12 10:54 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Hi Pablo,
>> Could you recheck in detail patches 3/16 and 4/16?
>> If there is no flaws in the translation engine, we might just go for
>> it at it is.
> I'm not convinced that this approach is the way to go. In the payload
> case, the number of instruction tuples will explode, and you will have
> to iterate many times to find the corresponding parser.
There are many ways to reduce drastically such lookup process, current
implementation is just here to prove it works.
I have actually some code for that, by extending the instruction
declaration with extra infos, it kills looping. Not finished though.
(have also a solution for not pre-loading all extensions, btw)
Actually NAT is probably the worst example. I should have implemented 2
or 3 totally different other extensions.
Because nat exists as its own expression in nftables, so indeed it's
really easy to pick it up in an expression list.
if (expr == "nat") parse_nat();
But it's not going to be that simple with complex set of different
expressions representing one extension.
Of course it's can still work with programmatic way but it's going to be
really annoying in maintenance, entangled code, bug prone etc...
Since every time you will support a new extension, code will need to change.
With my approach: no code change needed anymore, just declaring the
right instruction which is very trivial.
> Anyway, I really think we have to start by converting nft to ipt
> command state in one single patch, as your patches 11-13 do, we need
> it for whatever approach we decide to follow. If you don't have time
> to make that rebase, I'll try to find some spare time to work on it.
> Let me know.
I can find time.
Tomasz
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2013-08-12 10:54 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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
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).