Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -1857,10 +1857,16 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx,
	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,
				struct netlink_callback *cb)
{
	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_table *table;
	const struct nft_chain *chain;
@@ -1877,7 +1883,15 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
			continue;

		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) {
				if (ctx && ctx->chain[0] &&
				    strcmp(ctx->chain, chain->name) != 0)
					continue;

				list_for_each_entry_rcu(rule, &chain->rules, list) {
					if (!nft_is_active(net, rule))
						goto cont;
@@ -1907,6 +1921,12 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
	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,
			     struct sk_buff *skb, const struct nlmsghdr *nlh,
			     const struct nlattr * const nla[])
@@ -1924,7 +1944,25 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
	if (nlh->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.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);
	}