diff options
Diffstat (limited to 'iptables/nft.c')
-rw-r--r-- | iptables/nft.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/iptables/nft.c b/iptables/nft.c index 247a60aa..f1f0d9d6 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -2698,3 +2698,197 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag) return NFT_CMP_EQ; } + +#define NFT_COMPAT_EXPR_MAX 8 + +static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = { + "match", + "target", + "payload", + "meta", + "cmp", + "bitwise", + "counter", + "immediate" +}; + + +static int nft_is_expr_compatible(const char *name) +{ + int i; + + for (i = 0; i < NFT_COMPAT_EXPR_MAX; i++) { + if (strcmp(supported_exprs[i], name) == 0) + return 0; + } + + return 1; +} + +static int nft_is_rule_compatible(struct nftnl_rule *rule) +{ + struct nftnl_expr_iter *iter; + struct nftnl_expr *expr; + int ret = 0; + + 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 (nft_is_expr_compatible(name) == 0) { + expr = nftnl_expr_iter_next(iter); + continue; + } + + ret = 1; + break; + } + + nftnl_expr_iter_destroy(iter); + return ret; +} + +static int nft_is_chain_compatible(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) + continue; + + 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; + int ret = 0; + + 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)) + goto next; + + const char *table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE); + const char *name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME); + + if (nft_is_chain_compatible(table, name) == 1) { + ret = 1; + break; + } + +next: + chain = nftnl_chain_list_iter_next(iter); + } + + nftnl_chain_list_iter_destroy(iter); + nftnl_chain_list_free(list); + return ret; +} + +static int nft_is_table_compatible(const char *name) +{ + int i; + + for (i = 0; i < TABLES_MAX; i++) { + if (strcmp(xtables_ipv4[i].name, name) == 0) + return 0; + } + + return 1; +} + +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; + int ret = 0; + + 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 (nft_is_table_compatible(name) == 0) { + table = nftnl_table_list_iter_next(iter); + continue; + } + + ret = 1; + break; + } + + nftnl_table_list_iter_destroy(iter); + nftnl_table_list_free(list); + return ret; +} + +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 = 0; + + 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) + break; + + rule = nftnl_rule_list_iter_next(iter); + } + + nftnl_rule_list_iter_destroy(iter); + return ret; +} |