netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Pablo M. Bermudo Garay" <pablombg@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: pablo@netfilter.org, "Pablo M. Bermudo Garay" <pablombg@gmail.com>
Subject: [PATCH iptables 2/3] xtables-compat: check if nft ruleset is compatible
Date: Sun, 21 Aug 2016 20:10:26 +0200	[thread overview]
Message-ID: <20160821181027.14622-2-pablombg@gmail.com> (raw)
In-Reply-To: <20160821181027.14622-1-pablombg@gmail.com>

This patch adds a verification of the compatibility between the nft
ruleset and iptables. If the nft ruleset is not compatible with
iptables, the execution stops and an error message is displayed to the
user.

This checking is triggered by xtables-compat -L and xtables-compat-save
commands.

Signed-off-by: Pablo M. Bermudo Garay <pablombg@gmail.com>
---
 iptables/nft.c          | 166 ++++++++++++++++++++++++++++++++++++++++++++++++
 iptables/nft.h          |   2 +
 iptables/xtables-save.c |   5 ++
 iptables/xtables.c      |   5 ++
 4 files changed, 178 insertions(+)

diff --git a/iptables/nft.c b/iptables/nft.c
index 247a60a..7389689 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2698,3 +2698,169 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag)
 
 	return NFT_CMP_EQ;
 }
+
+static int nft_is_rule_compatible(struct nftnl_rule *rule)
+{
+	struct nftnl_expr_iter *iter;
+	struct nftnl_expr *expr;
+
+	iter = nftnl_expr_iter_create(rule);
+	if (iter == NULL)
+		return -1;
+
+	expr = nftnl_expr_iter_next(iter);
+	while (expr != NULL) {
+		const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
+
+		if (strcmp(name, "counter")   &&
+		    strcmp(name, "match")     &&
+		    strcmp(name, "target")    &&
+		    strcmp(name, "payload")   &&
+		    strcmp(name, "meta")      &&
+		    strcmp(name, "bitwise")   &&
+		    strcmp(name, "cmp")       &&
+		    strcmp(name, "immediate") &&
+		    strcmp(name, "match")     &&
+		    strcmp(name, "target")) {
+			nftnl_expr_iter_destroy(iter);
+			return 1;
+		}
+
+		expr = nftnl_expr_iter_next(iter);
+	}
+
+	nftnl_expr_iter_destroy(iter);
+	return 0;
+}
+
+static int check_builtin_chain(const char *table, const char *chain)
+{
+	const char *cur_table;
+	struct builtin_chain *chains;
+	int i, j;
+
+	for (i = 0; i < TABLES_MAX; i++) {
+		cur_table = xtables_ipv4[i].name;
+		chains = xtables_ipv4[i].chains;
+		if (strcmp(table, cur_table) == 0) {
+			for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
+				if (strcmp(chain, chains[j].name) == 0)
+					return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+static int nft_are_chains_compatible(struct nft_handle *h)
+{
+	struct nftnl_chain_list *list;
+	struct nftnl_chain_list_iter *iter;
+	struct nftnl_chain *chain;
+
+	list = nftnl_chain_list_get(h);
+	if (list == NULL)
+		return -1;
+
+	iter = nftnl_chain_list_iter_create(list);
+	if (iter == NULL)
+		return -1;
+
+	chain = nftnl_chain_list_iter_next(iter);
+	while (chain != NULL) {
+		if (nft_chain_builtin(chain)) {
+			const char *table = nftnl_chain_get(chain,
+							    NFTNL_CHAIN_TABLE);
+			const char *name = nftnl_chain_get(chain,
+							   NFTNL_CHAIN_NAME);
+
+			if (check_builtin_chain(table, name) == 1) {
+				nftnl_chain_list_iter_destroy(iter);
+				nftnl_chain_list_free(list);
+				return 1;
+			}
+		}
+
+		chain = nftnl_chain_list_iter_next(iter);
+	}
+
+	nftnl_chain_list_iter_destroy(iter);
+	nftnl_chain_list_free(list);
+	return 0;
+}
+
+static int nft_are_tables_compatible(struct nft_handle *h)
+{
+	struct nftnl_table_list *list;
+	struct nftnl_table_list_iter *iter;
+	struct nftnl_table *table;
+
+	list = nftnl_table_list_get(h);
+	if (list == NULL)
+		return -1;
+
+	iter = nftnl_table_list_iter_create(list);
+	if (iter == NULL)
+		return -1;
+
+	table = nftnl_table_list_iter_next(iter);
+	while (table != NULL) {
+		const char *name = nftnl_table_get(table, NFTNL_TABLE_NAME);
+
+		if (strcmp(name, "filter") &&
+		    strcmp(name, "nat")    &&
+		    strcmp(name, "mangle") &&
+		    strcmp(name, "raw")    &&
+		    strcmp(name, "security")) {
+			nftnl_table_list_iter_destroy(iter);
+			nftnl_table_list_free(list);
+			return 1;
+		}
+
+		table = nftnl_table_list_iter_next(iter);
+	}
+
+	nftnl_table_list_iter_destroy(iter);
+	nftnl_table_list_free(list);
+	return 0;
+}
+
+int nft_is_ruleset_compatible(struct nft_handle *h)
+{
+
+	struct nftnl_rule_list *list;
+	struct nftnl_rule_list_iter *iter;
+	struct nftnl_rule *rule;
+	int ret;
+
+	ret = nft_are_tables_compatible(h);
+	if (ret != 0)
+		return ret;
+
+	ret = nft_are_chains_compatible(h);
+	if (ret != 0)
+		return ret;
+
+	list = nft_rule_list_get(h);
+	if (list == NULL)
+		return -1;
+
+	iter = nftnl_rule_list_iter_create(list);
+	if (iter == NULL)
+		return -1;
+
+	rule = nftnl_rule_list_iter_next(iter);
+	while (rule != NULL) {
+		ret = nft_is_rule_compatible(rule);
+		if (ret != 0) {
+			nftnl_rule_list_iter_destroy(iter);
+			return ret;
+		}
+
+		rule = nftnl_rule_list_iter_next(iter);
+	}
+
+	nftnl_rule_list_iter_destroy(iter);
+	return 0;
+}
diff --git a/iptables/nft.h b/iptables/nft.h
index bcabf42..f5449db 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -181,4 +181,6 @@ int nft_arp_rule_insert(struct nft_handle *h, const char *chain,
 
 void nft_rule_to_arpt_entry(struct nftnl_rule *r, struct arpt_entry *fw);
 
+int nft_is_ruleset_compatible(struct nft_handle *h);
+
 #endif
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index 50b5b5a..50ae8a5 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -138,6 +138,11 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
 		exit(1);
 	}
 
+	if (nft_is_ruleset_compatible(&h) == 1) {
+		printf("WARNING: You're using features from nft that we cannot map to iptables, please keep using nft.\n\n");
+		exit(EXIT_SUCCESS);
+	}
+
 	if (dump) {
 		do_output(&h, tablename, show_counters);
 		exit(0);
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 48b9c51..ceae441 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -1253,6 +1253,11 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
 	case CMD_LIST:
 	case CMD_LIST|CMD_ZERO:
 	case CMD_LIST|CMD_ZERO_NUM:
+		if (nft_is_ruleset_compatible(h) == 1) {
+			printf("WARNING: You're using features from nft that we cannot map to iptables, please keep using nft.\n\n");
+			exit(EXIT_SUCCESS);
+		}
+
 		ret = list_entries(h, p.chain, p.table, p.rulenum,
 				   cs.options & OPT_VERBOSE,
 				   cs.options & OPT_NUMERIC,
-- 
2.9.3


  reply	other threads:[~2016-08-21 18:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-21 18:10 [PATCH iptables 1/3] xtables-compat: remove useless functions Pablo M. Bermudo Garay
2016-08-21 18:10 ` Pablo M. Bermudo Garay [this message]
2016-08-21 20:25   ` [PATCH iptables 2/3] xtables-compat: check if nft ruleset is compatible Arturo Borrero Gonzalez
2016-08-22  9:56   ` Pablo Neira Ayuso
2016-08-21 18:10 ` [PATCH iptables 3/3] xtables-compat: add rule cache Pablo M. Bermudo Garay
2016-08-22  9:51 ` [PATCH iptables 1/3] xtables-compat: remove useless functions Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160821181027.14622-2-pablombg@gmail.com \
    --to=pablombg@gmail.com \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).