--- zzzz-none-000/linux-4.4.271/net/netfilter/nf_conntrack_ecache.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/net/netfilter/nf_conntrack_ecache.c 2023-04-19 10:22:30.000000000 +0000 @@ -18,6 +18,9 @@ #include #include #include +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +#include +#endif #include #include #include @@ -115,6 +118,52 @@ /* 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); @@ -165,8 +214,15 @@ out_unlock: rcu_read_unlock(); } +#endif EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); +#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) { @@ -187,8 +243,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) { @@ -202,6 +266,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,