]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: Review is_*_compatible() routines
authorPhil Sutter <phil@nwl.cc>
Thu, 20 Dec 2018 15:09:05 +0000 (16:09 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 27 Dec 2018 18:18:21 +0000 (19:18 +0100)
- 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>
iptables/nft.c

index 1fca1f17147f6d70969e02e83d5f69b25ffefdd3..5032c718b33a9590e7101b1f8292d744a7b669b6 100644 (file)
@@ -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;
 }