summaryrefslogtreecommitdiffstats
path: root/iptables/nft.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-12-20 16:09:05 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-12-27 19:18:21 +0100
commite774b15299c271a4c7570899591cf1b7960477ea (patch)
treebb4632bfae2adfcf1bdf699ef6f9a205d57a7211 /iptables/nft.c
parent9523b2e9dee3d9b4439214092c496542ce9f434e (diff)
nft: Review is_*_compatible() routines
- Call to nft_table_builtin_find() in nft_is_table_compatible() is not needed, as it is repeated in the latter call to nft_chain_list_get() by nft_are_chains_compatible(). - Turn nft_is_chain_compatible(), nft_is_rule_compatible() and nft_is_expr_compatible() into callbacks for use with respective foreach functions. - nft_are_chains_compatible() is not needed anymore due to foreach function use. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'iptables/nft.c')
-rw-r--r--iptables/nft.c153
1 files changed, 55 insertions, 98 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 1fca1f17..5032c718 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -3115,7 +3115,7 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
};
-static int nft_is_expr_compatible(const struct nftnl_expr *expr)
+static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data)
{
const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
int i;
@@ -3130,138 +3130,95 @@ static int nft_is_expr_compatible(const struct nftnl_expr *expr)
nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0)
return 0;
- return 1;
+ return -1;
}
-static bool nft_is_rule_compatible(struct nftnl_rule *rule)
-{
- struct nftnl_expr_iter *iter;
- struct nftnl_expr *expr;
- bool compatible = false;
-
- iter = nftnl_expr_iter_create(rule);
- if (iter == NULL)
- return false;
+struct nft_is_rule_compatible_data {
+ const char *tablename;
+};
- expr = nftnl_expr_iter_next(iter);
- while (expr != NULL) {
- if (nft_is_expr_compatible(expr) == 0) {
- expr = nftnl_expr_iter_next(iter);
- continue;
- }
+static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data)
+{
+ const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
+ struct nft_is_rule_compatible_data *d = data;
- compatible = true;
- break;
- }
+ /* ignore rules belonging to a different table */
+ if (strcmp(table, d->tablename))
+ return 0;
- nftnl_expr_iter_destroy(iter);
- return compatible;
+ return nftnl_expr_foreach(rule, nft_is_expr_compatible, NULL);
}
-static int nft_is_chain_compatible(const struct nft_handle *h,
- const struct nftnl_chain *chain)
+static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
{
- const char *table, *name, *type, *cur_table;
- const struct builtin_chain *chains;
- int i, j, prio;
+ const struct builtin_chain *chains = NULL, *chain = NULL;
+ const char *table, *name, *type;
+ struct nft_handle *h = data;
enum nf_inet_hooks hook;
+ int i, prio;
- table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
- name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
- type = nftnl_chain_get(chain, NFTNL_CHAIN_TYPE);
- prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO);
- hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM);
+ if (!nft_chain_builtin(c))
+ return 0;
+ /* find chain's table in builtin tables */
+ table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
for (i = 0; i < NFT_TABLE_MAX; i++) {
- cur_table = h->tables[i].name;
- chains = h->tables[i].chains;
+ const char *cur_table = h->tables[i].name;
- if (!cur_table || strcmp(table, cur_table) != 0)
+ if (!cur_table || strcmp(cur_table, table))
continue;
- for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
- if (strcmp(name, chains[j].name) != 0)
- continue;
-
- if (strcmp(type, chains[j].type) == 0 &&
- prio == chains[j].prio &&
- hook == chains[j].hook)
- return 0;
- break;
- }
+ chains = h->tables[i].chains;
+ break;
}
-
- return 1;
-}
-
-static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename)
-{
- struct nftnl_chain_list *list;
- struct nftnl_chain_list_iter *iter;
- struct nftnl_chain *chain;
- int ret = 0;
-
- list = nft_chain_list_get(h, tablename);
- if (list == NULL)
- return -1;
-
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
+ if (!chains)
return -1;
- chain = nftnl_chain_list_iter_next(iter);
- while (chain != NULL) {
- if (!nft_chain_builtin(chain))
- goto next;
+ /* find chain in builtin chain list */
+ name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ for (i = 0; i < NF_INET_NUMHOOKS && chains[i].name; i++) {
+ if (strcmp(name, chains[i].name))
+ continue;
- ret = nft_is_chain_compatible(h, chain);
- if (ret != 0)
- break;
-next:
- chain = nftnl_chain_list_iter_next(iter);
+ chain = &chains[i];
+ break;
}
+ if (!chain)
+ return -1;
- nftnl_chain_list_iter_destroy(iter);
+ /* compare properties */
+ type = nftnl_chain_get_str(c, NFTNL_CHAIN_TYPE);
+ prio = nftnl_chain_get_u32(c, NFTNL_CHAIN_PRIO);
+ hook = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM);
+ if (strcmp(type, chain->type) ||
+ prio != chain->prio ||
+ hook != chain->hook)
+ return -1;
- return ret;
+ return 0;
}
bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
{
+ struct nft_is_rule_compatible_data rcd = {
+ .tablename = tablename
+ };
+ struct nftnl_chain_list *clist;
struct nftnl_rule_list *list;
- struct nftnl_rule_list_iter *iter;
- struct nftnl_rule *rule;
- int ret = 0;
- if (!nft_table_builtin_find(h, tablename))
+ clist = nft_chain_list_get(h, tablename);
+ if (clist == NULL)
return false;
- ret = nft_are_chains_compatible(h, tablename);
- if (ret != 0)
+ if (nftnl_chain_list_foreach(clist, nft_is_chain_compatible, h))
return false;
list = nft_rule_list_get(h);
if (list == NULL)
return true;
- iter = nftnl_rule_list_iter_create(list);
- if (iter == NULL)
- return true;
-
- rule = nftnl_rule_list_iter_next(iter);
- while (rule != NULL) {
- const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
-
- if (strcmp(table, tablename))
- goto next_rule;
-
- ret = nft_is_rule_compatible(rule);
- if (ret != 0)
- break;
-next_rule:
- rule = nftnl_rule_list_iter_next(iter);
- }
+ if (nftnl_rule_list_foreach(list, nft_is_rule_compatible, &rcd))
+ return false;
- nftnl_rule_list_iter_destroy(iter);
- return ret == 0;
+ return true;
}