Commit 8daa8fde authored by Phil Sutter's avatar Phil Sutter Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: Introduce NFT_MSG_GETRULE_RESET



Analogous to NFT_MSG_GETOBJ_RESET, but for rules: Reset stateful
expressions like counters or quotas. The latter two are the only
consumers, adjust their 'dump' callbacks to respect the parameter
introduced earlier.

Signed-off-by: default avatarPhil Sutter <phil@nwl.cc>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 7d34aa3e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -383,7 +383,7 @@ int nft_expr_inner_parse(const struct nft_ctx *ctx, const struct nlattr *nla,
int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src);
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
		  const struct nft_expr *expr);
		  const struct nft_expr *expr, bool reset);
bool nft_expr_reduce_bitwise(struct nft_regs_track *track,
			     const struct nft_expr *expr);

+2 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ enum nft_verdicts {
 * @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes)
 * @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes)
 * @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes)
 * @NFT_MSG_GETRULE_RESET: get rules and reset stateful expressions (enum nft_obj_attributes)
 */
enum nf_tables_msg_types {
	NFT_MSG_NEWTABLE,
@@ -124,6 +125,7 @@ enum nf_tables_msg_types {
	NFT_MSG_NEWFLOWTABLE,
	NFT_MSG_GETFLOWTABLE,
	NFT_MSG_DELFLOWTABLE,
	NFT_MSG_GETRULE_RESET,
	NFT_MSG_MAX,
};

+33 −16
Original line number Diff line number Diff line
@@ -2759,7 +2759,7 @@ static const struct nla_policy nft_expr_policy[NFTA_EXPR_MAX + 1] = {
};

static int nf_tables_fill_expr_info(struct sk_buff *skb,
				    const struct nft_expr *expr)
				    const struct nft_expr *expr, bool reset)
{
	if (nla_put_string(skb, NFTA_EXPR_NAME, expr->ops->type->name))
		goto nla_put_failure;
@@ -2769,7 +2769,7 @@ static int nf_tables_fill_expr_info(struct sk_buff *skb,
							    NFTA_EXPR_DATA);
		if (data == NULL)
			goto nla_put_failure;
		if (expr->ops->dump(skb, expr, false) < 0)
		if (expr->ops->dump(skb, expr, reset) < 0)
			goto nla_put_failure;
		nla_nest_end(skb, data);
	}
@@ -2781,14 +2781,14 @@ static int nf_tables_fill_expr_info(struct sk_buff *skb,
};

int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
		  const struct nft_expr *expr)
		  const struct nft_expr *expr, bool reset)
{
	struct nlattr *nest;

	nest = nla_nest_start_noflag(skb, attr);
	if (!nest)
		goto nla_put_failure;
	if (nf_tables_fill_expr_info(skb, expr) < 0)
	if (nf_tables_fill_expr_info(skb, expr, reset) < 0)
		goto nla_put_failure;
	nla_nest_end(skb, nest);
	return 0;
@@ -3034,7 +3034,8 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
				    u32 flags, int family,
				    const struct nft_table *table,
				    const struct nft_chain *chain,
				    const struct nft_rule *rule, u64 handle)
				    const struct nft_rule *rule, u64 handle,
				    bool reset)
{
	struct nlmsghdr *nlh;
	const struct nft_expr *expr, *next;
@@ -3067,7 +3068,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
	if (list == NULL)
		goto nla_put_failure;
	nft_rule_for_each_expr(expr, next, rule) {
		if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
		if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr, reset) < 0)
			goto nla_put_failure;
	}
	nla_nest_end(skb, list);
@@ -3118,7 +3119,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,

	err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
				       event, flags, ctx->family, ctx->table,
				       ctx->chain, rule, handle);
				       ctx->chain, rule, handle, false);
	if (err < 0) {
		kfree_skb(skb);
		goto err;
@@ -3139,7 +3140,8 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
				  unsigned int *idx,
				  struct netlink_callback *cb,
				  const struct nft_table *table,
				  const struct nft_chain *chain)
				  const struct nft_chain *chain,
				  bool reset)
{
	struct net *net = sock_net(skb->sk);
	const struct nft_rule *rule, *prule;
@@ -3166,7 +3168,7 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
					NFT_MSG_NEWRULE,
					NLM_F_MULTI | NLM_F_APPEND,
					table->family,
					table, chain, rule, handle) < 0)
					table, chain, rule, handle, reset) < 0)
			return 1;

		nl_dump_check_consistent(cb, nlmsg_hdr(skb));
@@ -3189,6 +3191,10 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
	struct net *net = sock_net(skb->sk);
	int family = nfmsg->nfgen_family;
	struct nftables_pernet *nft_net;
	bool reset = false;

	if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
		reset = true;

	rcu_read_lock();
	nft_net = nft_pernet(net);
@@ -3213,14 +3219,15 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
				if (!nft_is_active(net, chain))
					continue;
				__nf_tables_dump_rules(skb, &idx,
						       cb, table, chain);
						       cb, table, chain, reset);
				break;
			}
			goto done;
		}

		list_for_each_entry_rcu(chain, &table->chains, list) {
			if (__nf_tables_dump_rules(skb, &idx, cb, table, chain))
			if (__nf_tables_dump_rules(skb, &idx,
						   cb, table, chain, reset))
				goto done;
		}

@@ -3291,6 +3298,7 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
	struct net *net = info->net;
	struct nft_table *table;
	struct sk_buff *skb2;
	bool reset = false;
	int err;

	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
@@ -3327,9 +3335,12 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
	if (!skb2)
		return -ENOMEM;

	if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
		reset = true;

	err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
				       info->nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
				       family, table, chain, rule, 0);
				       family, table, chain, rule, 0, reset);
	if (err < 0)
		goto err_fill_rule_info;

@@ -4104,7 +4115,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,

	if (set->num_exprs == 1) {
		nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
		if (nf_tables_fill_expr_info(skb, set->exprs[0]) < 0)
		if (nf_tables_fill_expr_info(skb, set->exprs[0], false) < 0)
			goto nla_put_failure;

		nla_nest_end(skb, nest);
@@ -4115,7 +4126,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,

		for (i = 0; i < set->num_exprs; i++) {
			if (nft_expr_dump(skb, NFTA_LIST_ELEM,
					  set->exprs[i]) < 0)
					  set->exprs[i], false) < 0)
				goto nla_put_failure;
		}
		nla_nest_end(skb, nest);
@@ -4946,7 +4957,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,

	if (num_exprs == 1) {
		expr = nft_setelem_expr_at(elem_expr, 0);
		if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr) < 0)
		if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr, false) < 0)
			return -1;

		return 0;
@@ -4957,7 +4968,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,

		nft_setelem_expr_foreach(expr, elem_expr, size) {
			expr = nft_setelem_expr_at(elem_expr, size);
			if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
			if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr, false) < 0)
				goto nla_put_failure;
		}
		nla_nest_end(skb, nest);
@@ -8311,6 +8322,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
		.attr_count	= NFTA_RULE_MAX,
		.policy		= nft_rule_policy,
	},
	[NFT_MSG_GETRULE_RESET] = {
		.call		= nf_tables_getrule,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_RULE_MAX,
		.policy		= nft_rule_policy,
	},
	[NFT_MSG_DELRULE] = {
		.call		= nf_tables_delrule,
		.type		= NFNL_CB_BATCH,
+1 −1
Original line number Diff line number Diff line
@@ -206,7 +206,7 @@ static int nft_counter_dump(struct sk_buff *skb,
{
	struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);

	return nft_counter_do_dump(skb, priv, false);
	return nft_counter_do_dump(skb, priv, reset);
}

static int nft_counter_init(const struct nft_ctx *ctx,
+2 −2
Original line number Diff line number Diff line
@@ -380,7 +380,7 @@ static int nft_dynset_dump(struct sk_buff *skb,
	if (priv->set->num_exprs == 0) {
		if (priv->num_exprs == 1) {
			if (nft_expr_dump(skb, NFTA_DYNSET_EXPR,
					  priv->expr_array[0]))
					  priv->expr_array[0], reset))
				goto nla_put_failure;
		} else if (priv->num_exprs > 1) {
			struct nlattr *nest;
@@ -391,7 +391,7 @@ static int nft_dynset_dump(struct sk_buff *skb,

			for (i = 0; i < priv->num_exprs; i++) {
				if (nft_expr_dump(skb, NFTA_LIST_ELEM,
						  priv->expr_array[i]))
						  priv->expr_array[i], reset))
					goto nla_put_failure;
			}
			nla_nest_end(skb, nest);
Loading