* [iptables-nftables - RFC PATCH 01/15] xtables: Add support for injecting xtables target into nft rule
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 02/15] xtables: add support for injecting xtables matches " Tomasz Bursztyka
` (13 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
configure.ac | 7 +++++++
extensions/GNUmakefile.in | 1 +
include/xtables.h.in | 5 +++++
iptables/nft.c | 20 ++++++++++++--------
4 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac
index 48a0d54..e228078 100644
--- a/configure.ac
+++ b/configure.ac
@@ -104,6 +104,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 4a8ff49..efb5502 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.in b/include/xtables.h.in
index 10b241f..767d53e 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -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
@@ -327,6 +329,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 72ac4b0..e773ace 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -609,17 +609,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;
}
@@ -745,7 +749,7 @@ nft_rule_add(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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 02/15] xtables: add support for injecting xtables matches into nft rule
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 01/15] xtables: Add support for injecting xtables target into nft rule Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 03/15] nft: Add nft expressions translation engine as a library Tomasz Bursztyka
` (12 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
include/xtables.h.in | 3 +++
iptables/nft.c | 20 ++++++++++++--------
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 767d53e..f2b2a23 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -261,6 +261,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 e773ace..90e86a1 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -573,17 +573,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;
}
@@ -725,7 +729,7 @@ nft_rule_add(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) {
ret = 0;
goto err;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [iptables-nftables - RFC PATCH 03/15] nft: Add nft expressions translation engine as a library
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 01/15] xtables: Add support for injecting xtables target into nft rule Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 02/15] xtables: add support for injecting xtables matches " Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 04/15] nft: Integrate nft translator engine in current core Tomasz Bursztyka
` (11 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: 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.
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 | 85 ++++++
libnfttrans/Makefile.am | 28 ++
libnfttrans/libnfttrans.pc.in | 11 +
libnfttrans/nft-translator.c | 618 ++++++++++++++++++++++++++++++++++++++++++
6 files changed, 746 insertions(+)
create mode 100644 include/nft-translator.h
create mode 100644 libnfttrans/Makefile.am
create mode 100644 libnfttrans/libnfttrans.pc.in
create mode 100644 libnfttrans/nft-translator.c
diff --git a/Makefile.am b/Makefile.am
index 4eb63eb..8123a87 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 e228078..6f144bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,5 +176,6 @@ 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.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..aa2eb7f
--- /dev/null
+++ b/include/nft-translator.h
@@ -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.
+ */
+
+#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_rulecontext_inhibate_instruction(struct nft_trans_rule_context *rule_ctx,
+ nft_trans_parse_instruction_f function);
+
+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.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..50db967
--- /dev/null
+++ b/libnfttrans/nft-translator.c
@@ -0,0 +1,618 @@
+/*
+ * (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;
+
+ /* Some complex instructions cannot be seen multiple times */
+ struct s_list *inhibited;
+};
+
+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);
+ }
+}
+
+static inline void s_list_free(struct s_list *list)
+{
+ _s_list_free(list, 0, NULL);
+}
+
+static inline void s_list_free_all(struct s_list *list)
+{
+ _s_list_free(list, 1, NULL);
+}
+
+static inline void s_list_free_full(struct s_list *list, free_function_f _free)
+{
+ _s_list_free(list, 1, _free);
+}
+
+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);
+ free(node);
+}
+
+void
+nft_trans_instruction_tree_destroy(struct nft_trans_instruction_tree *tree)
+{
+ if (tree == NULL)
+ return;
+
+ s_list_free_full(tree->nodes, _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);
+ }
+
+ if (rule_ctx->inhibited != NULL)
+ s_list_free(rule_ctx->inhibited);
+
+ 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;
+}
+
+int
+nft_trans_rulecontext_inhibate_instruction(struct nft_trans_rule_context *rule_ctx,
+ nft_trans_parse_instruction_f function)
+{
+ if (rule_ctx == NULL)
+ return -EINVAL;
+
+ rule_ctx->inhibited = s_list_prepend(rule_ctx->inhibited, function);
+
+ return 0;
+}
+
+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 bool is_instruction_inhibited(struct s_list *inhibited, void *data)
+{
+ for (; inhibited != NULL; inhibited = inhibited->next) {
+ if (inhibited->data == data)
+ return true;
+ }
+
+ return false;
+}
+
+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 (is_instruction_inhibited(rule_ctx->inhibited,
+ function))
+ continue;
+
+ 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_all(nft_trans_instructions);
+ position = pos->next;
+ }
+
+ destroy_nft_trans_rule_context(rule_ctx);
+
+ return 0;
+
+error:
+ s_list_free_all(nft_trans_instructions);
+ 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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 04/15] nft: Integrate nft translator engine in current core
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (2 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 03/15] nft: Add nft expressions translation engine as a library Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 05/15] nft: Manage xtables target parsing through translation tree Tomasz Bursztyka
` (10 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
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 | 23 +++--
iptables/nft-shared.h | 10 +-
iptables/nft.c | 249 +++++++++++++++++++++++++++++++++++---------------
6 files changed, 225 insertions(+), 91 deletions(-)
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index fb26a32..2b6a037 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 51ee422..4b8f146 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 61c660a..e5c8db9 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 5762952..030c55d 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -290,21 +290,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;
}
@@ -316,6 +311,18 @@ void get_cmp_data(struct nft_rule_expr_iter *iter,
*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);
+}
+
void print_num(uint64_t number, unsigned int format)
{
if (format & FMT_KILOMEGAGIGA) {
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index c59ab21..2c199b4 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -44,7 +44,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 +83,8 @@ void parse_meta(struct nft_rule_expr *e, uint8_t key, char *iniface,
unsigned char *outiface_mask, uint8_t *invflags);
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 print_num(uint64_t number, unsigned int format);
@@ -121,6 +124,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 90e86a1..155a9d3 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -46,12 +46,16 @@
#include <netinet/in.h> /* inet_ntoa */
#include <arpa/inet.h>
+#include <nft-translator.h>
#include "nft.h"
#include "xshared.h" /* proto_to_name */
#include "nft-shared.h"
#include "xtables-config-parser.h"
+static void initiate_nft_translation_tree(void);
+
static void *nft_fn;
+struct nft_trans_instruction_tree *xt_nft_tree;
static int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
int (*cb)(const struct nlmsghdr *nlh, void *data),
@@ -403,6 +407,8 @@ int nft_init(struct nft_handle *h)
}
h->portid = mnl_socket_get_portid(h->nl);
+ initiate_nft_translation_tree();
+
return 0;
}
@@ -1697,106 +1703,142 @@ match_different(const struct xt_entry_match *a,
return 0;
}
-static void
-nft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- int family, struct iptables_command_state *cs)
-{
- 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;
-
- 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);
-}
-
-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;
+}
+
+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_to_cs_data *i2cs = user_data;
+ struct nft_family_ops *ops;
+ struct nft_rule_expr *e;
+ uint8_t key;
+
+ e = nft_trans_instruction_context_get_expr(first);
+ if (!nft_rule_expr_is_set(e, NFT_EXPR_META_KEY))
+ return -1;
+
+ key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
+ ops = nft_family_ops_lookup(i2cs->family);
+
+ e = nft_trans_instruction_context_get_expr(second);
+ ops->parse_meta(e, key, i2cs->cs);
+
+ return 0;
+}
+
+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 void
nft_rule_to_iptables_command_state(struct nft_rule *r,
struct iptables_command_state *cs)
{
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
-
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return;
-
- expr = nft_rule_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
+ struct nft_to_cs_data i2cs = {};
- 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);
- }
+ i2cs.family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
+ i2cs.cs = cs;
- expr = nft_rule_expr_iter_next(iter);
- }
+ nft_trans_rule_translate_to_instructions(xt_nft_tree, r, NULL, &i2cs);
- nft_rule_expr_iter_destroy(iter);
+ 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 int matches_howmany(struct xtables_rule_match *matches)
@@ -2778,6 +2820,69 @@ static void xtables_config_perror(uint32_t flags, const char *fmt, ...)
va_end(args);
}
+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,
+};
+
+static void initiate_nft_translation_tree(void)
+{
+ xt_nft_tree = nft_trans_instruction_tree_new();
+ if (xt_nft_tree == NULL)
+ return;
+
+ 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);
+}
+
int nft_xtables_config_load(struct nft_handle *h, const char *filename,
uint32_t flags)
{
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [iptables-nftables - RFC PATCH 05/15] nft: Manage xtables target parsing through translation tree
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (3 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 04/15] nft: Integrate nft translator engine in current core Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 06/15] nft: Manage xtables matches through nft " Tomasz Bursztyka
` (9 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/Makefile.am | 1 +
iptables/nft-xt-ext.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
iptables/nft-xt-ext.h | 12 +++++++
iptables/nft.c | 3 ++
4 files changed, 104 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 2b6a037..8bc38ca 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-xt-ext.c b/iptables/nft-xt-ext.c
new file mode 100644
index 0000000..ad9a7f7
--- /dev/null
+++ b/iptables/nft-xt-ext.c
@@ -0,0 +1,88 @@
+/*
+ * (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 <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;
+
+ /* There cannot be more than 1 target */
+ nft_trans_rulecontext_inhibate_instruction(rule_ctx,
+ nft_parse_xt_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);
diff --git a/iptables/nft.c b/iptables/nft.c
index 155a9d3..2f00486 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -51,6 +51,7 @@
#include "xshared.h" /* proto_to_name */
#include "nft-shared.h"
#include "xtables-config-parser.h"
+#include "nft-xt-ext.h"
static void initiate_nft_translation_tree(void);
@@ -2881,6 +2882,8 @@ static void initiate_nft_translation_tree(void)
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);
+
+ nft_xt_ext_into_translation_tree(xt_nft_tree);
}
int nft_xtables_config_load(struct nft_handle *h, const char *filename,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [iptables-nftables - RFC PATCH 06/15] nft: Manage xtables matches through nft translation tree
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (4 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 05/15] nft: Manage xtables target parsing through translation tree Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 07/15] nft: Add support for xtables extensions callback to change cs Tomasz Bursztyka
` (8 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
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 ad9a7f7..387d6fa 100644
--- a/iptables/nft-xt-ext.c
+++ b/iptables/nft-xt-ext.c
@@ -67,6 +67,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,
@@ -77,12 +126,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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 07/15] nft: Add support for xtables extensions callback to change cs
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (5 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 06/15] nft: Manage xtables matches through nft " Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 08/15] xtables: Add support for registering nft translation function for target Tomasz Bursztyka
` (7 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft-xt-ext.c | 20 ++++++++++++++++++++
iptables/nft-xt-ext.h | 2 ++
iptables/nft.c | 3 ++-
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/iptables/nft-xt-ext.c b/iptables/nft-xt-ext.c
index 387d6fa..ffc53f0 100644
--- a/iptables/nft-xt-ext.c
+++ b/iptables/nft-xt-ext.c
@@ -146,3 +146,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);
diff --git a/iptables/nft.c b/iptables/nft.c
index 2f00486..57bc3d8 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1831,7 +1831,8 @@ 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;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [iptables-nftables - RFC PATCH 08/15] xtables: Add support for registering nft translation function for target
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (6 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 07/15] nft: Add support for xtables extensions callback to change cs Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 09/15] xtables: Add support for registering nft translation function for match Tomasz Bursztyka
` (6 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
extensions/GNUmakefile.in | 2 +-
include/xtables.h.in | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index efb5502..8f8d775 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.in b/include/xtables.h.in
index f2b2a23..1658842 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -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
@@ -334,6 +335,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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 09/15] xtables: Add support for registering nft translation function for match
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (7 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 08/15] xtables: Add support for registering nft translation function for target Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 10/15] nft: Register all relevant xtables extensions into translation tree Tomasz Bursztyka
` (5 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
include/xtables.h.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 1658842..592aae9 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -264,6 +264,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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 10/15] nft: Register all relevant xtables extensions into translation tree
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (8 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 09/15] xtables: Add support for registering nft translation function for match Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 11/15] nft: Refactor firewall printing so it reuses already parsed cs struct Tomasz Bursztyka
` (4 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
include/xtables.h.in | 3 +++
iptables/nft-xt-ext.c | 13 +++++++++++++
2 files changed, 16 insertions(+)
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 592aae9..0f02470 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -403,6 +403,9 @@ 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 ffc53f0..2ce8b70 100644
--- a/iptables/nft-xt-ext.c
+++ b/iptables/nft-xt-ext.c
@@ -138,12 +138,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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 11/15] nft: Refactor firewall printing so it reuses already parsed cs struct
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (9 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 10/15] nft: Register all relevant xtables extensions into translation tree Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 12/15] nft: Refactor rule deletion so it compares both cs structure Tomasz Bursztyka
` (3 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 122 ++++++---------------------------------------------------
1 file changed, 11 insertions(+), 111 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 57bc3d8..5fd5bb9 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2296,95 +2296,18 @@ print_header(unsigned int format, const char *chain, const char *pol,
}
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);
-}
-
-static void
print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
unsigned int num, unsigned int format)
{
- const struct xtables_target *target = NULL;
- const char *targname = NULL;
- const void *targinfo = NULL;
- int family;
+ struct xtables_rule_match *matchp;
struct nft_family_ops *ops;
uint8_t flags = 0;
- struct nft_rule_expr_iter *iter;
- struct nft_rule_expr *expr;
- struct xt_entry_target *t;
- size_t target_len = 0;
-
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return;
-
- 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);
+ int family;
family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
ops = nft_family_ops_lookup(family);
- flags = ops->print_firewall(cs, targname, num, format);
+ flags = ops->print_firewall(cs, cs->jumpto, num, format);
if (format & FMT_NOTABLE)
fputs(" ", stdout);
@@ -2394,40 +2317,17 @@ print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
printf("[goto] ");
#endif
- iter = nft_rule_expr_iter_create(r);
- if (iter == NULL)
- return;
-
- 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);
+ for (matchp = cs->matches; matchp; matchp = matchp->next) {
+ if (matchp->match->print != NULL)
+ matchp->match->print(NULL, matchp->match->m,
+ format & FMT_NUMERIC);
}
- nft_rule_expr_iter_destroy(iter);
- t = calloc(1, sizeof(struct xt_entry_target) + target_len);
- if (t == NULL)
- return;
-
- /* emulate struct xt_entry_match since ->print needs it */
- memcpy((void *)&t->data, targinfo, target_len);
-
- if (targname) {
- 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
- printf("[%ld bytes of unknown target data] ",
- target_len);
+ if (cs->target != NULL) {
+ if (cs->target->print != NULL)
+ cs->target->print(NULL, cs->target->t,
+ format & FMT_NUMERIC);
}
- free(t);
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [iptables-nftables - RFC PATCH 12/15] nft: Refactor rule deletion so it compares both cs structure
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (10 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 11/15] nft: Refactor firewall printing so it reuses already parsed cs struct Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 13/15] nft: Remove useless function Tomasz Bursztyka
` (2 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 197 +++++++++++----------------------------------------------
1 file changed, 37 insertions(+), 160 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 5fd5bb9..4476fcd 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1843,187 +1843,64 @@ nft_rule_to_iptables_command_state(struct nft_rule *r,
i2cs.cs->jumpto = "";
}
-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;
-
- for (matchp = matches; matchp; matchp = matchp->next) {
- struct xt_entry_match *m = matchp->match->m;
+ struct xtables_rule_match *mp_1;
+ struct xtables_rule_match *mp_2;
+ 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 (target_1->t->u.user.target_size != target_2->t->u.user.target_size)
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);
+ if (memcmp(target_1->t->data, target_2->t->data,
+ target_1->t->u.user.target_size -
+ sizeof(*target_1->t)) != 0)
+ return false;
return true;
}
@@ -2103,18 +1980,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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 13/15] nft: Remove useless function
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (11 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 12/15] nft: Refactor rule deletion so it compares both cs structure Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 14/15] xtables: nft: Complete refactoring on how rules are saved Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 15/15] xtables: Support pure nft expressions for DNAT extension Tomasz Bursztyka
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 27 ---------------------------
1 file changed, 27 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 4476fcd..009c3b3 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1677,33 +1677,6 @@ next:
return 0;
}
-static inline int
-match_different(const struct xt_entry_match *a,
- const unsigned char *a_elems,
- const unsigned char *b_elems,
- unsigned char **maskptr)
-{
- const struct xt_entry_match *b;
- unsigned int i;
-
- /* Offset of b is the same as a. */
- b = (void *)b_elems + ((unsigned char *)a - a_elems);
-
- if (a->u.match_size != b->u.match_size)
- return 1;
-
- if (strcmp(a->u.user.name, b->u.user.name) != 0)
- return 1;
-
- *maskptr += XT_ALIGN(sizeof(*a));
-
- for (i = 0; i < a->u.match_size - XT_ALIGN(sizeof(*a)); i++)
- if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
- return 1;
- *maskptr += i;
- return 0;
-}
-
static int nft_parse_counters(struct nft_trans_rule_context *rule_ctx,
struct nft_trans_instruction_context *first,
struct nft_trans_instruction_context *useless,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [iptables-nftables - RFC PATCH 14/15] xtables: nft: Complete refactoring on how rules are saved
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (12 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 13/15] nft: Remove useless function Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 15/15] xtables: Support pure nft expressions for DNAT extension Tomasz Bursztyka
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft-ipv4.c | 122 ++++++--------------
iptables/nft-ipv6.c | 72 +++++-------
iptables/nft-shared.c | 73 ++++++++++--
iptables/nft-shared.h | 13 ++-
iptables/nft.c | 284 +++++++---------------------------------------
iptables/nft.h | 8 +-
iptables/xtables-events.c | 21 ++--
7 files changed, 189 insertions(+), 404 deletions(-)
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 4b8f146..3c2a40f 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)
{
@@ -311,6 +223,38 @@ static uint8_t nft_ipv4_print_firewall(const struct iptables_command_state *cs,
return cs->fw.ip.flags;
}
+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)
@@ -360,10 +304,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 e5c8db9..138328f 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)
{
@@ -209,6 +167,34 @@ static uint8_t nft_ipv6_print_firewall(const struct iptables_command_state *cs,
return cs->fw6.ipv6.flags;
}
+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)
{
@@ -278,10 +264,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 030c55d..2954ff5 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -311,18 +311,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);
-}
-
void print_num(uint64_t number, unsigned int format)
{
if (format & FMT_KILOMEGAGIGA) {
@@ -412,6 +400,67 @@ 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);
+ }
+
+}
+
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 2c199b4..45eccf5 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -40,8 +40,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,
@@ -52,6 +50,8 @@ struct nft_family_ops {
uint8_t (*print_firewall)(const struct iptables_command_state *cs,
const char *targname, 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);
};
@@ -85,14 +85,19 @@ 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 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 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);
struct nft_family_ops *nft_family_ops_lookup(int family);
diff --git a/iptables/nft.c b/iptables/nft.c
index 009c3b3..ad8b951 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -53,8 +53,6 @@
#include "xtables-config-parser.h"
#include "nft-xt-ext.h"
-static void initiate_nft_translation_tree(void);
-
static void *nft_fn;
struct nft_trans_instruction_tree *xt_nft_tree;
@@ -408,7 +406,7 @@ int nft_init(struct nft_handle *h)
}
h->portid = mnl_socket_get_portid(h->nl);
- initiate_nft_translation_tree();
+ nft_initiate_translation_tree();
return 0;
}
@@ -804,218 +802,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;
-
- printf("-m %s", name);
-
- 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);
-
- /* 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;
-
- printf("-j %s", name);
-
- 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);
-
- /* 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) {
@@ -1027,33 +834,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");
}
@@ -1235,11 +1033,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);
@@ -1795,9 +1597,8 @@ static int nft_parse_ip_addresses(struct nft_trans_rule_context *rule_ctx,
return 0;
}
-static void
-nft_rule_to_iptables_command_state(struct nft_rule *r,
- struct iptables_command_state *cs)
+void nft_rule_to_iptables_command_state(struct nft_rule *r,
+ struct iptables_command_state *cs)
{
struct nft_to_cs_data i2cs = {};
@@ -1943,13 +1744,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;
@@ -2318,7 +2118,7 @@ static void
list_save(const struct iptables_command_state *cs, struct nft_rule *r,
unsigned int num, unsigned int format)
{
- nft_rule_print_save(r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
+ nft_rule_print_save(cs, r, NFT_RULE_APPEND, format);
}
static int
@@ -2622,7 +2422,7 @@ static struct nft_trans_instruction nft_ipt_ip_addr_2 = {
.function = nft_parse_ip_addresses,
};
-static void initiate_nft_translation_tree(void)
+void nft_initiate_translation_tree(void)
{
xt_nft_tree = nft_trans_instruction_tree_new();
if (xt_nft_tree == NULL)
diff --git a/iptables/nft.h b/iptables/nft.h
index a647671..8597308 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -64,7 +64,13 @@ 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_initiate_translation_tree(void);
+void
+nft_rule_to_iptables_command_state(struct nft_rule *r,
+ struct iptables_command_state *cs);
+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] 16+ messages in thread
* [iptables-nftables - RFC PATCH 15/15] xtables: Support pure nft expressions for DNAT extension
2013-07-19 15:17 [iptables-nftables - RFC PATCH 00/15] Xtables extensions: full support (pure nft or compat layer) Tomasz Bursztyka
` (13 preceding siblings ...)
2013-07-19 15:17 ` [iptables-nftables - RFC PATCH 14/15] xtables: nft: Complete refactoring on how rules are saved Tomasz Bursztyka
@ 2013-07-19 15:17 ` Tomasz Bursztyka
14 siblings, 0 replies; 16+ messages in thread
From: Tomasz Bursztyka @ 2013-07-19 15:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
extensions/libipt_DNAT.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 220 insertions(+)
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index 466c9de..92b4ef2 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 <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_tables.h>
enum {
O_TO_DEST = 0,
@@ -242,6 +243,223 @@ 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_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 & IP_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 & IP_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_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 |= IP_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 |= IP_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 +472,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] 16+ messages in thread