summaryrefslogtreecommitdiff
path: root/net/netfilter/nf_conntrack_netlink.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2022-04-11 13:01:17 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2022-05-13 18:52:16 +0200
commit0d3cc504ba9cdcff76346306c37eb1ea01e60a86 (patch)
treefba95c168499f8b53a49e80199a374a2bc047ac2 /net/netfilter/nf_conntrack_netlink.c
parent2ed3bf188b33630cf9d93b996ebf001847a00b5a (diff)
netfilter: conntrack: include ecache dying list in dumps
The new pernet dying list includes conntrack entries that await delivery of the 'destroy' event via ctnetlink. The old percpu dying list will be removed soon. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nf_conntrack_netlink.c')
-rw-r--r--net/netfilter/nf_conntrack_netlink.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 924d766e6c53..a4ec2aad2187 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -62,6 +62,7 @@ struct ctnetlink_list_dump_ctx {
struct nf_conn *last;
unsigned int cpu;
bool done;
+ bool retrans_done;
};
static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
@@ -1802,6 +1803,48 @@ out:
static int
ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct ctnetlink_list_dump_ctx *ctx = (void *)cb->ctx;
+ struct nf_conn *last = ctx->last;
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ const struct net *net = sock_net(skb->sk);
+ struct nf_conntrack_net_ecache *ecache_net;
+ struct nf_conntrack_tuple_hash *h;
+ struct hlist_nulls_node *n;
+#endif
+
+ if (ctx->retrans_done)
+ return ctnetlink_dump_list(skb, cb, true);
+
+ ctx->last = NULL;
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ ecache_net = nf_conn_pernet_ecache(net);
+ spin_lock_bh(&ecache_net->dying_lock);
+
+ hlist_nulls_for_each_entry(h, n, &ecache_net->dying_list, hnnode) {
+ struct nf_conn *ct;
+ int res;
+
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (last && last != ct)
+ continue;
+
+ res = ctnetlink_dump_one_entry(skb, cb, ct, true);
+ if (res < 0) {
+ spin_unlock_bh(&ecache_net->dying_lock);
+ nf_ct_put(last);
+ return skb->len;
+ }
+
+ nf_ct_put(last);
+ last = NULL;
+ }
+
+ spin_unlock_bh(&ecache_net->dying_lock);
+#endif
+ nf_ct_put(last);
+ ctx->retrans_done = true;
+
return ctnetlink_dump_list(skb, cb, true);
}