Let nf_ct_delete handle delivery of the DESTROY event.
Based on earlier patch from Pablo Neira.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
 
 /* Iterate over all conntracks: if iter returns true, it's deleted. */
 extern void
-nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data);
+nf_ct_iterate_cleanup(struct net *net,
+                     int (*iter)(struct nf_conn *i, void *data),
+                     void *data, u32 portid, int report);
 extern void nf_conntrack_free(struct nf_conn *ct);
 extern struct nf_conn *
 nf_conntrack_alloc(struct net *net, u16 zone,
 
                NF_CT_ASSERT(dev->ifindex != 0);
 
                nf_ct_iterate_cleanup(net, device_cmp,
-                                     (void *)(long)dev->ifindex);
+                                     (void *)(long)dev->ifindex, 0, 0);
        }
 
        return NOTIFY_DONE;
 
 
        if (event == NETDEV_DOWN)
                nf_ct_iterate_cleanup(net, device_cmp,
-                                     (void *)(long)dev->ifindex);
+                                     (void *)(long)dev->ifindex, 0, 0);
 
        return NOTIFY_DONE;
 }
 
 
 void nf_ct_iterate_cleanup(struct net *net,
                           int (*iter)(struct nf_conn *i, void *data),
-                          void *data)
+                          void *data, u32 portid, int report)
 {
        struct nf_conn *ct;
        unsigned int bucket = 0;
        while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) {
                /* Time to push up daises... */
                if (del_timer(&ct->timeout))
-                       death_by_timeout((unsigned long)ct);
+                       nf_ct_delete(ct, portid, report);
 
                /* ... else the timer will get him soon. */
 
 }
 EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup);
 
-struct __nf_ct_flush_report {
-       u32 portid;
-       int report;
-};
-
-static int kill_report(struct nf_conn *i, void *data)
-{
-       struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data;
-       struct nf_conn_tstamp *tstamp;
-
-       tstamp = nf_conn_tstamp_find(i);
-       if (tstamp && tstamp->stop == 0)
-               tstamp->stop = ktime_to_ns(ktime_get_real());
-
-       /* If we fail to deliver the event, death_by_timeout() will retry */
-       if (nf_conntrack_event_report(IPCT_DESTROY, i,
-                                     fr->portid, fr->report) < 0)
-               return 1;
-
-       /* Avoid the delivery of the destroy event in death_by_timeout(). */
-       set_bit(IPS_DYING_BIT, &i->status);
-       return 1;
-}
-
 static int kill_all(struct nf_conn *i, void *data)
 {
        return 1;
 
 void nf_conntrack_flush_report(struct net *net, u32 portid, int report)
 {
-       struct __nf_ct_flush_report fr = {
-               .portid = portid,
-               .report = report,
-       };
-       nf_ct_iterate_cleanup(net, kill_report, &fr);
+       nf_ct_iterate_cleanup(net, kill_all, NULL, portid, report);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_flush_report);
 
 i_see_dead_people:
        busy = 0;
        list_for_each_entry(net, net_exit_list, exit_list) {
-               nf_ct_iterate_cleanup(net, kill_all, NULL);
+               nf_ct_iterate_cleanup(net, kill_all, NULL, 0, 0);
                nf_ct_release_dying_list(net);
                if (atomic_read(&net->ct.count) != 0)
                        busy = 1;
 
        nf_ct_l3proto_unregister_sysctl(net, proto);
 
        /* Remove all contrack entries for this protocol */
-       nf_ct_iterate_cleanup(net, kill_l3proto, proto);
+       nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0);
 }
 EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_unregister);
 
        nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
 
        /* Remove all contrack entries for this protocol */
-       nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
+       nf_ct_iterate_cleanup(net, kill_l4proto, l4proto, 0, 0);
 }
 EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister);
 
 
 
        rtnl_lock();
        for_each_net(net)
-               nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
+               nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean, 0, 0);
        rtnl_unlock();
 }
 
        rtnl_lock();
 
        for_each_net(net)
-               nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
+               nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean, 0, 0);
        rtnl_unlock();
 }
 
 {
        struct nf_nat_proto_clean clean = {};
 
-       nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
+       nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean, 0, 0);
        synchronize_rcu();
        nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
 }