Commit 6e1f760e authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_tables: allow to filter out rules by table and chain

If the table and/or chain attributes are set in a rule dump request,
we filter out the rules based on this selection.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent cc37c1ad
...@@ -1857,10 +1857,16 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx, ...@@ -1857,10 +1857,16 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx,
return err; return err;
} }
struct nft_rule_dump_ctx {
char table[NFT_TABLE_MAXNAMELEN];
char chain[NFT_CHAIN_MAXNAMELEN];
};
static int nf_tables_dump_rules(struct sk_buff *skb, static int nf_tables_dump_rules(struct sk_buff *skb,
struct netlink_callback *cb) struct netlink_callback *cb)
{ {
const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
const struct nft_rule_dump_ctx *ctx = cb->data;
const struct nft_af_info *afi; const struct nft_af_info *afi;
const struct nft_table *table; const struct nft_table *table;
const struct nft_chain *chain; const struct nft_chain *chain;
...@@ -1877,7 +1883,15 @@ static int nf_tables_dump_rules(struct sk_buff *skb, ...@@ -1877,7 +1883,15 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
continue; continue;
list_for_each_entry_rcu(table, &afi->tables, list) { list_for_each_entry_rcu(table, &afi->tables, list) {
if (ctx && ctx->table[0] &&
strcmp(ctx->table, table->name) != 0)
continue;
list_for_each_entry_rcu(chain, &table->chains, list) { list_for_each_entry_rcu(chain, &table->chains, list) {
if (ctx && ctx->chain[0] &&
strcmp(ctx->chain, chain->name) != 0)
continue;
list_for_each_entry_rcu(rule, &chain->rules, list) { list_for_each_entry_rcu(rule, &chain->rules, list) {
if (!nft_is_active(net, rule)) if (!nft_is_active(net, rule))
goto cont; goto cont;
...@@ -1907,6 +1921,12 @@ static int nf_tables_dump_rules(struct sk_buff *skb, ...@@ -1907,6 +1921,12 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
return skb->len; return skb->len;
} }
static int nf_tables_dump_rules_done(struct netlink_callback *cb)
{
kfree(cb->data);
return 0;
}
static int nf_tables_getrule(struct net *net, struct sock *nlsk, static int nf_tables_getrule(struct net *net, struct sock *nlsk,
struct sk_buff *skb, const struct nlmsghdr *nlh, struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const nla[]) const struct nlattr * const nla[])
...@@ -1924,7 +1944,25 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, ...@@ -1924,7 +1944,25 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
if (nlh->nlmsg_flags & NLM_F_DUMP) { if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = { struct netlink_dump_control c = {
.dump = nf_tables_dump_rules, .dump = nf_tables_dump_rules,
.done = nf_tables_dump_rules_done,
}; };
if (nla[NFTA_RULE_TABLE] || nla[NFTA_RULE_CHAIN]) {
struct nft_rule_dump_ctx *ctx;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
if (nla[NFTA_RULE_TABLE])
nla_strlcpy(ctx->table, nla[NFTA_RULE_TABLE],
sizeof(ctx->table));
if (nla[NFTA_RULE_CHAIN])
nla_strlcpy(ctx->chain, nla[NFTA_RULE_CHAIN],
sizeof(ctx->chain));
c.data = ctx;
}
return netlink_dump_start(nlsk, skb, nlh, &c); return netlink_dump_start(nlsk, skb, nlh, &c);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment