--- zzzz-none-000/linux-5.4.213/net/netfilter/nf_conntrack_ecache.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/net/netfilter/nf_conntrack_ecache.c 2024-05-29 11:20:02.000000000 +0000 @@ -17,6 +17,9 @@ #include #include #include +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +#include +#endif #include #include #include @@ -117,6 +120,7 @@ schedule_delayed_work(&ctnet->ecache_dwork, delay); } +#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, u32 portid, int report) { @@ -172,9 +176,56 @@ return ret; } EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report); +#endif /* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +void nf_ct_deliver_cached_events(struct nf_conn *ct) +{ + unsigned long events, missed; + struct nf_conntrack_ecache *e; + struct nf_ct_event item; + struct net *net = nf_ct_net(ct); + int ret = 0; + + e = nf_ct_ecache_find(ct); + if (!e) + return; + + events = xchg(&e->cache, 0); + + if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct) || !events) + return; + + /* + * We make a copy of the missed event cache without taking + * the lock, thus we may send missed events twice. However, + * this does not harm and it happens very rarely. + */ + missed = e->missed; + + if (!((events | missed) & e->ctmask)) + return; + + item.ct = ct; + item.portid = 0; + item.report = 0; + + atomic_notifier_call_chain(&net->ct.nf_conntrack_chain, + events | missed, &item); + + if (likely(ret >= 0 && !missed)) + return; + + spin_lock_bh(&ct->lock); + if (ret < 0) + e->missed |= events; + else + e->missed &= ~missed; + spin_unlock_bh(&ct->lock); +} +#else void nf_ct_deliver_cached_events(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); @@ -225,6 +276,7 @@ out_unlock: rcu_read_unlock(); } +#endif EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, @@ -257,6 +309,12 @@ rcu_read_unlock(); } +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb); +} +#else int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *new) { @@ -277,8 +335,16 @@ mutex_unlock(&nf_ct_ecache_mutex); return ret; } +#endif EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, + nb); +} +#else void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *new) { @@ -292,6 +358,7 @@ mutex_unlock(&nf_ct_ecache_mutex); /* synchronize_rcu() is called from ctnetlink_exit. */ } +#endif EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); int nf_ct_expect_register_notifier(struct net *net,