From 0d3cc504ba9cdcff76346306c37eb1ea01e60a86 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Apr 2022 13:01:17 +0200 Subject: 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 Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 2 ++ net/netfilter/nf_conntrack_ecache.c | 10 +++++++ net/netfilter/nf_conntrack_netlink.c | 43 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index a6135b5030dd..b57d73785e4d 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -164,6 +164,8 @@ void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state); void nf_conntrack_ecache_pernet_init(struct net *net); void nf_conntrack_ecache_pernet_fini(struct net *net); +struct nf_conntrack_net_ecache *nf_conn_pernet_ecache(const struct net *net); + static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) { return net->ct.ecache_dwork_pending; diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 2752859479b2..334b2b4e5e8b 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -38,6 +38,16 @@ enum retry_state { STATE_DONE, }; +struct nf_conntrack_net_ecache *nf_conn_pernet_ecache(const struct net *net) +{ + struct nf_conntrack_net *cnet = nf_ct_pernet(net); + + return &cnet->ecache; +} +#if IS_MODULE(CONFIG_NF_CT_NETLINK) +EXPORT_SYMBOL_GPL(nf_conn_pernet_ecache); +#endif + static enum retry_state ecache_work_evict_list(struct nf_conntrack_net *cnet) { unsigned long stop = jiffies + ECACHE_MAX_JIFFIES; 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); } -- cgit v1.2.3