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

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