static void nf_tables_rule_notify(const struct nft_ctx *ctx,
				  const struct nft_rule *rule, int event)
{
	struct nftables_pernet *nft_net = nft_pernet(ctx->net);
	const struct nft_rule *prule;
	struct sk_buff *skb;
	u64 handle = 0;
	u16 flags = 0;
	int err;

	if (!ctx->report &&
	    !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
		return;

	skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
	if (skb == NULL)
		goto err;

	if (event == NFT_MSG_NEWRULE &&
	    !list_is_first(&rule->list, &ctx->chain->rules) &&
	    !list_is_last(&rule->list, &ctx->chain->rules)) {
		prule = list_prev_entry(rule, list);
		handle = prule->handle;
	}
	if (ctx->flags & (NLM_F_APPEND | NLM_F_REPLACE))
		flags |= NLM_F_APPEND;
	if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
		flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);

	err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
				       event, flags, ctx->family, ctx->table,
				       ctx->chain, rule, handle);
	if (err < 0) {
		kfree_skb(skb);
		goto err;
	}

	nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
	return;
err:
	nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
}
static void nf_tables_rule_notify(const struct nft_ctx *ctx,
				  const struct nft_rule *rule, int event)
{
	struct nftables_pernet *nft_net = nft_pernet(ctx->net);
	const struct nft_rule *prule;
	struct sk_buff *skb;
	u64 handle = 0;
	u16 flags = 0;
	int err;

	if (!ctx->report &&
	    !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
		return;

	skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
	if (skb == NULL)
		goto err;

	if (event == NFT_MSG_NEWRULE &&
	    !list_is_first(&rule->list, &ctx->chain->rules) &&
	    !list_is_last(&rule->list, &ctx->chain->rules)) {
		prule = list_prev_entry(rule, list);
		handle = prule->handle;
	}
	if (ctx->flags & (NLM_F_APPEND | NLM_F_REPLACE))
		flags |= NLM_F_APPEND;
	if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
		flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);

	err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
				       event, flags, ctx->family, ctx->table,
				       ctx->chain, rule, handle);
	if (err < 0) {
		kfree_skb(skb);
		goto err;
	}

	nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
	return;
err:
	nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
}