Blame SOURCES/0014-nft-Review-is_-_compatible-routines.patch

029dc7
From 109b8f2d637b5e4b1a6ff6994297203834e4e77a Mon Sep 17 00:00:00 2001
029dc7
From: Phil Sutter <phil@nwl.cc>
029dc7
Date: Thu, 20 Dec 2018 16:09:05 +0100
029dc7
Subject: [PATCH] nft: Review is_*_compatible() routines
029dc7
029dc7
- Call to nft_table_builtin_find() in nft_is_table_compatible() is not
029dc7
  needed, as it is repeated in the latter call to nft_chain_list_get()
029dc7
  by nft_are_chains_compatible().
029dc7
029dc7
- Turn nft_is_chain_compatible(), nft_is_rule_compatible() and
029dc7
  nft_is_expr_compatible() into callbacks for use with respective
029dc7
  foreach functions.
029dc7
029dc7
- nft_are_chains_compatible() is not needed anymore due to foreach
029dc7
  function use.
029dc7
029dc7
Signed-off-by: Phil Sutter <phil@nwl.cc>
029dc7
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
029dc7
(cherry picked from commit e774b15299c271a4c7570899591cf1b7960477ea)
029dc7
Signed-off-by: Phil Sutter <psutter@redhat.com>
029dc7
---
029dc7
 iptables/nft.c | 153 ++++++++++++++++++-------------------------------
029dc7
 1 file changed, 55 insertions(+), 98 deletions(-)
029dc7
029dc7
diff --git a/iptables/nft.c b/iptables/nft.c
029dc7
index 1fca1f17147f6..5032c718b33a9 100644
029dc7
--- a/iptables/nft.c
029dc7
+++ b/iptables/nft.c
029dc7
@@ -3115,7 +3115,7 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
029dc7
 };
029dc7
 
029dc7
 
029dc7
-static int nft_is_expr_compatible(const struct nftnl_expr *expr)
029dc7
+static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data)
029dc7
 {
029dc7
 	const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
029dc7
 	int i;
029dc7
@@ -3130,138 +3130,95 @@ static int nft_is_expr_compatible(const struct nftnl_expr *expr)
029dc7
 	    nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0)
029dc7
 		return 0;
029dc7
 
029dc7
-	return 1;
029dc7
+	return -1;
029dc7
 }
029dc7
 
029dc7
-static bool nft_is_rule_compatible(struct nftnl_rule *rule)
029dc7
-{
029dc7
-	struct nftnl_expr_iter *iter;
029dc7
-	struct nftnl_expr *expr;
029dc7
-	bool compatible = false;
029dc7
-
029dc7
-	iter = nftnl_expr_iter_create(rule);
029dc7
-	if (iter == NULL)
029dc7
-		return false;
029dc7
+struct nft_is_rule_compatible_data {
029dc7
+	const char *tablename;
029dc7
+};
029dc7
 
029dc7
-	expr = nftnl_expr_iter_next(iter);
029dc7
-	while (expr != NULL) {
029dc7
-		if (nft_is_expr_compatible(expr) == 0) {
029dc7
-			expr = nftnl_expr_iter_next(iter);
029dc7
-			continue;
029dc7
-		}
029dc7
+static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data)
029dc7
+{
029dc7
+	const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
029dc7
+	struct nft_is_rule_compatible_data *d = data;
029dc7
 
029dc7
-		compatible = true;
029dc7
-		break;
029dc7
-	}
029dc7
+	/* ignore rules belonging to a different table */
029dc7
+	if (strcmp(table, d->tablename))
029dc7
+		return 0;
029dc7
 
029dc7
-	nftnl_expr_iter_destroy(iter);
029dc7
-	return compatible;
029dc7
+	return nftnl_expr_foreach(rule, nft_is_expr_compatible, NULL);
029dc7
 }
029dc7
 
029dc7
-static int nft_is_chain_compatible(const struct nft_handle *h,
029dc7
-				   const struct nftnl_chain *chain)
029dc7
+static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
029dc7
 {
029dc7
-	const char *table, *name, *type, *cur_table;
029dc7
-	const struct builtin_chain *chains;
029dc7
-	int i, j, prio;
029dc7
+	const struct builtin_chain *chains = NULL, *chain = NULL;
029dc7
+	const char *table, *name, *type;
029dc7
+	struct nft_handle *h = data;
029dc7
 	enum nf_inet_hooks hook;
029dc7
+	int i, prio;
029dc7
 
029dc7
-	table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
029dc7
-	name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
029dc7
-	type = nftnl_chain_get(chain, NFTNL_CHAIN_TYPE);
029dc7
-	prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO);
029dc7
-	hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM);
029dc7
+	if (!nft_chain_builtin(c))
029dc7
+		return 0;
029dc7
 
029dc7
+	/* find chain's table in builtin tables */
029dc7
+	table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
029dc7
 	for (i = 0; i < NFT_TABLE_MAX; i++) {
029dc7
-		cur_table = h->tables[i].name;
029dc7
-		chains = h->tables[i].chains;
029dc7
+		const char *cur_table = h->tables[i].name;
029dc7
 
029dc7
-		if (!cur_table || strcmp(table, cur_table) != 0)
029dc7
+		if (!cur_table || strcmp(cur_table, table))
029dc7
 			continue;
029dc7
 
029dc7
-		for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
029dc7
-			if (strcmp(name, chains[j].name) != 0)
029dc7
-				continue;
029dc7
-
029dc7
-			if (strcmp(type, chains[j].type) == 0 &&
029dc7
-			    prio == chains[j].prio &&
029dc7
-			    hook == chains[j].hook)
029dc7
-				return 0;
029dc7
-			break;
029dc7
-		}
029dc7
+		chains = h->tables[i].chains;
029dc7
+		break;
029dc7
 	}
029dc7
-
029dc7
-	return 1;
029dc7
-}
029dc7
-
029dc7
-static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename)
029dc7
-{
029dc7
-	struct nftnl_chain_list *list;
029dc7
-	struct nftnl_chain_list_iter *iter;
029dc7
-	struct nftnl_chain *chain;
029dc7
-	int ret = 0;
029dc7
-
029dc7
-	list = nft_chain_list_get(h, tablename);
029dc7
-	if (list == NULL)
029dc7
-		return -1;
029dc7
-
029dc7
-	iter = nftnl_chain_list_iter_create(list);
029dc7
-	if (iter == NULL)
029dc7
+	if (!chains)
029dc7
 		return -1;
029dc7
 
029dc7
-	chain = nftnl_chain_list_iter_next(iter);
029dc7
-	while (chain != NULL) {
029dc7
-		if (!nft_chain_builtin(chain))
029dc7
-			goto next;
029dc7
+	/* find chain in builtin chain list */
029dc7
+	name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
029dc7
+	for (i = 0; i < NF_INET_NUMHOOKS && chains[i].name; i++) {
029dc7
+		if (strcmp(name, chains[i].name))
029dc7
+			continue;
029dc7
 
029dc7
-		ret = nft_is_chain_compatible(h, chain);
029dc7
-		if (ret != 0)
029dc7
-			break;
029dc7
-next:
029dc7
-		chain = nftnl_chain_list_iter_next(iter);
029dc7
+		chain = &chains[i];
029dc7
+		break;
029dc7
 	}
029dc7
+	if (!chain)
029dc7
+		return -1;
029dc7
 
029dc7
-	nftnl_chain_list_iter_destroy(iter);
029dc7
+	/* compare properties */
029dc7
+	type = nftnl_chain_get_str(c, NFTNL_CHAIN_TYPE);
029dc7
+	prio = nftnl_chain_get_u32(c, NFTNL_CHAIN_PRIO);
029dc7
+	hook = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM);
029dc7
+	if (strcmp(type, chain->type) ||
029dc7
+	    prio != chain->prio ||
029dc7
+	    hook != chain->hook)
029dc7
+		return -1;
029dc7
 
029dc7
-	return ret;
029dc7
+	return 0;
029dc7
 }
029dc7
 
029dc7
 bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
029dc7
 {
029dc7
+	struct nft_is_rule_compatible_data rcd = {
029dc7
+		.tablename = tablename
029dc7
+	};
029dc7
+	struct nftnl_chain_list *clist;
029dc7
 	struct nftnl_rule_list *list;
029dc7
-	struct nftnl_rule_list_iter *iter;
029dc7
-	struct nftnl_rule *rule;
029dc7
-	int ret = 0;
029dc7
 
029dc7
-	if (!nft_table_builtin_find(h, tablename))
029dc7
+	clist = nft_chain_list_get(h, tablename);
029dc7
+	if (clist == NULL)
029dc7
 		return false;
029dc7
 
029dc7
-	ret = nft_are_chains_compatible(h, tablename);
029dc7
-	if (ret != 0)
029dc7
+	if (nftnl_chain_list_foreach(clist, nft_is_chain_compatible, h))
029dc7
 		return false;
029dc7
 
029dc7
 	list = nft_rule_list_get(h);
029dc7
 	if (list == NULL)
029dc7
 		return true;
029dc7
 
029dc7
-	iter = nftnl_rule_list_iter_create(list);
029dc7
-	if (iter == NULL)
029dc7
-		return true;
029dc7
-
029dc7
-	rule = nftnl_rule_list_iter_next(iter);
029dc7
-	while (rule != NULL) {
029dc7
-		const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
029dc7
-
029dc7
-		if (strcmp(table, tablename))
029dc7
-			goto next_rule;
029dc7
-
029dc7
-		ret = nft_is_rule_compatible(rule);
029dc7
-		if (ret != 0)
029dc7
-			break;
029dc7
-next_rule:
029dc7
-		rule = nftnl_rule_list_iter_next(iter);
029dc7
-	}
029dc7
+	if (nftnl_rule_list_foreach(list, nft_is_rule_compatible, &rcd))
029dc7
+		return false;
029dc7
 
029dc7
-	nftnl_rule_list_iter_destroy(iter);
029dc7
-	return ret == 0;
029dc7
+	return true;
029dc7
 }
029dc7
-- 
029dc7
2.21.0
029dc7