}
int nft_cache_add_chain(struct nft_handle *h, const struct builtin_table *t,
- struct nftnl_chain *c)
+ struct nftnl_chain *c, bool fake)
{
const char *cname = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- struct nft_chain *nc = nft_chain_alloc(c);
+ struct nft_chain *nc = nft_chain_alloc(c, fake);
int ret;
if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
goto out;
}
- nft_cache_add_chain(h, t, c);
+ nft_cache_add_chain(h, t, c, false);
return MNL_CB_OK;
out:
nftnl_chain_free(c);
struct hlist_node hnode;
struct nft_chain **base_slot;
struct nftnl_chain *nftnl;
+ bool fake;
};
#define CHAIN_NAME_HSIZE 512
struct hlist_head names[CHAIN_NAME_HSIZE];
};
-struct nft_chain *nft_chain_alloc(struct nftnl_chain *nftnl);
+struct nft_chain *nft_chain_alloc(struct nftnl_chain *nftnl, bool fake);
void nft_chain_free(struct nft_chain *c);
struct nft_chain_list *nft_chain_list_alloc(void);
if (!fake)
batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
- nft_cache_add_chain(h, table, c);
+ nft_cache_add_chain(h, table, c, fake);
}
/* find if built-in table already exists */
static void nft_chain_builtin_init(struct nft_handle *h,
const struct builtin_table *table)
{
+ struct nft_chain *c;
int i;
/* Initialize built-in chains if they don't exist yet */
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
- if (nft_chain_find(h, table->name, table->chains[i].name))
- continue;
-
- nft_chain_builtin_add(h, table, &table->chains[i], false);
+ c = nft_chain_find(h, table->name, table->chains[i].name);
+ if (!c) {
+ nft_chain_builtin_add(h, table,
+ &table->chains[i], false);
+ } else if (c->fake) {
+ batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c->nftnl);
+ c->fake = false;
+ }
}
}
{
const struct builtin_table *t;
const struct builtin_chain *c;
+ struct nft_chain *nc;
if (!h->cache_init)
return 0;
if (!c)
return -1;
- if (h->cache->table[t->type].base_chains[c->hook])
- return 0;
-
- nft_chain_builtin_add(h, t, c, false);
+ nc = h->cache->table[t->type].base_chains[c->hook];
+ if (!nc) {
+ nft_chain_builtin_add(h, t, c, false);
+ } else if (nc->fake) {
+ batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, nc->nftnl);
+ nc->fake = false;
+ }
return 0;
}
if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c))
return 0;
- nft_cache_add_chain(h, t, c);
+ nft_cache_add_chain(h, t, c, false);
/* the core expects 1 for success and 0 for error */
return 1;
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
created = true;
- nft_cache_add_chain(h, t, c);
+ nft_cache_add_chain(h, t, c, false);
} else {
c = nc->nftnl;