}
static int fetch_chain_cache(struct nft_handle *h,
- const struct builtin_table *t)
+ const struct builtin_table *t,
+ const char *chain)
{
struct nftnl_chain_list_cb_data d = {
.h = h,
return -1;
}
- nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
- NLM_F_DUMP, h->seq);
+ if (t && chain) {
+ struct nftnl_chain *c = nftnl_chain_alloc();
+
+ if (!c)
+ return -1;
+
+ nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN,
+ h->family, NLM_F_ACK,
+ h->seq);
+ nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, t->name);
+ nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
+ nftnl_chain_nlmsg_build_payload(nlh, c);
+ nftnl_chain_free(c);
+ } else {
+ nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN,
+ h->family, NLM_F_DUMP,
+ h->seq);
+ }
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d);
if (ret < 0 && errno == EINTR)
return 0;
}
-static int fetch_rule_cache(struct nft_handle *h, const struct builtin_table *t)
+static int fetch_rule_cache(struct nft_handle *h,
+ const struct builtin_table *t, const char *chain)
{
int i;
- if (t)
- return nftnl_chain_list_foreach(h->cache->table[t->type].chains,
- nft_rule_list_update, h);
+ if (t) {
+ struct nftnl_chain_list *list;
+ struct nftnl_chain *c;
+
+ list = h->cache->table[t->type].chains;
+
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
+ return nft_rule_list_update(c, h);
+ }
+ return nftnl_chain_list_foreach(list, nft_rule_list_update, h);
+ }
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
return 0;
}
-static void __nft_build_cache(struct nft_handle *h, enum nft_cache_level level,
- const struct builtin_table *t)
+static void
+__nft_build_cache(struct nft_handle *h, enum nft_cache_level level,
+ const struct builtin_table *t, const char *chain)
{
uint32_t genid_start, genid_stop;
break;
/* fall through */
case NFT_CL_TABLES:
- fetch_chain_cache(h, t);
+ fetch_chain_cache(h, t, chain);
if (level == NFT_CL_CHAINS)
break;
/* fall through */
case NFT_CL_CHAINS:
- fetch_rule_cache(h, t);
+ fetch_rule_cache(h, t, chain);
if (level == NFT_CL_RULES)
break;
/* fall through */
goto retry;
}
- if (!t)
+ if (!t && !chain)
h->cache_level = level;
else if (h->cache_level < NFT_CL_TABLES)
h->cache_level = NFT_CL_TABLES;
h->nft_genid = genid_start;
}
-void nft_build_cache(struct nft_handle *h)
+void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c)
{
- if (h->cache_level < NFT_CL_RULES)
- __nft_build_cache(h, NFT_CL_RULES, NULL);
+ const struct builtin_table *t;
+ const char *table, *chain;
+
+ if (!c)
+ return __nft_build_cache(h, NFT_CL_RULES, NULL, NULL);
+
+ table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
+ chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ t = nft_table_builtin_find(h, table);
+ __nft_build_cache(h, NFT_CL_RULES, t, chain);
}
void nft_fake_cache(struct nft_handle *h)
__nft_flush_cache(h);
h->cache_level = NFT_CL_NONE;
- __nft_build_cache(h, level, NULL);
+ __nft_build_cache(h, level, NULL, NULL);
}
void nft_release_cache(struct nft_handle *h)
struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
{
- __nft_build_cache(h, NFT_CL_TABLES, NULL);
+ __nft_build_cache(h, NFT_CL_TABLES, NULL, NULL);
return h->cache->tables;
}
-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
- const char *table)
+struct nftnl_chain_list *
+nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain)
{
const struct builtin_table *t;
if (!t)
return NULL;
- __nft_build_cache(h, NFT_CL_CHAINS, t);
+ __nft_build_cache(h, NFT_CL_CHAINS, t, chain);
return h->cache->table[t->type].chains;
}
struct nft_handle;
void nft_fake_cache(struct nft_handle *h);
-void nft_build_cache(struct nft_handle *h);
+void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c);
void nft_rebuild_cache(struct nft_handle *h);
void nft_release_cache(struct nft_handle *h);
void flush_chain_cache(struct nft_handle *h, const char *tablename);
void flush_rule_cache(struct nftnl_chain *c);
-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
- const char *table);
+struct nftnl_chain_list *
+nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain);
struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h);
#endif /* _NFT_CACHE_H_ */
static void nft_chain_builtin_init(struct nft_handle *h,
const struct builtin_table *table)
{
- struct nftnl_chain_list *list = nft_chain_list_get(h, table->name);
+ struct nftnl_chain_list *list = nft_chain_list_get(h, table->name, NULL);
struct nftnl_chain *c;
int i;
if (h->family == NFPROTO_BRIDGE) {
c = nft_chain_find(h, table, chain);
if (c && !nft_chain_builtin(c))
- nft_build_cache(h);
+ nft_build_cache(h, c);
}
nft_fn = nft_rule_append;
struct nftnl_chain *c;
int ret = 0;
- nft_build_cache(h);
-
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, NULL);
if (!list)
return 0;
c = nftnl_chain_list_iter_next(iter);
while (c) {
+ nft_build_cache(h, c);
ret = nft_chain_save_rules(h, c, format);
if (ret != 0)
break;
nft_fn = nft_rule_flush;
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (list == NULL) {
ret = 1;
goto err;
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (list)
nftnl_chain_list_add(c, list);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (list)
nftnl_chain_list_add(c, list);
/* This triggers required policy rule deletion. */
if (h->family == NFPROTO_BRIDGE)
- nft_build_cache(h);
+ nft_build_cache(h, c);
/* XXX This triggers a fast lookup from the kernel. */
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
nft_fn = nft_chain_user_del;
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (list == NULL)
return 0;
{
struct nftnl_chain_list *list;
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (list == NULL)
return NULL;
struct nftnl_rule_iter *iter;
bool found = false;
- nft_build_cache(h);
+ nft_build_cache(h, c);
if (rulenum >= 0)
/* Delete by rule number case */
if (!nft_is_table_compatible(h, table))
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (!list)
return 0;
if (!nft_is_table_compatible(h, table))
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (!list)
return 0;
else
return 0;
- nft_build_cache(h);
+ nft_build_cache(h, c);
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval);
return 1;
struct nftnl_chain *c;
int ret = 0;
- list = nft_chain_list_get(h, table);
+ list = nft_chain_list_get(h, table, chain);
if (list == NULL)
goto err;
enum nf_inet_hooks hook;
int prio;
- nft_build_cache(h);
+ nft_build_cache(h, c);
if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL))
return -1;
{
struct nftnl_chain_list *clist;
- clist = nft_chain_list_get(h, tablename);
+ clist = nft_chain_list_get(h, tablename, NULL);
if (clist == NULL)
return false;
{
struct nftnl_chain_list *chain_list;
- chain_list = nft_chain_list_get(h, table);
+ chain_list = nft_chain_list_get(h, table, NULL);
if (chain_list == NULL)
xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n");
if (!h->noflush)
nft_fake_cache(h);
else
- nft_build_cache(h);
+ nft_build_cache(h, NULL);
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), p->in)) {
return 0;
}
- chain_list = nft_chain_list_get(h, tablename);
+ chain_list = nft_chain_list_get(h, tablename, NULL);
if (!chain_list)
return 0;