aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--net/netfilter/nf_conntrack_core.c25
-rw-r--r--net/netfilter/nf_conntrack_netlink.c2
3 files changed, 11 insertions, 18 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index f1494feba79f..caca0c4d6b4b 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -182,7 +182,7 @@ __nf_conntrack_find(struct net *net, u16 zone,
182 182
183extern int nf_conntrack_hash_check_insert(struct nf_conn *ct); 183extern int nf_conntrack_hash_check_insert(struct nf_conn *ct);
184extern void nf_ct_delete_from_lists(struct nf_conn *ct); 184extern void nf_ct_delete_from_lists(struct nf_conn *ct);
185extern void nf_ct_insert_dying_list(struct nf_conn *ct); 185extern void nf_ct_dying_timeout(struct nf_conn *ct);
186 186
187extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); 187extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report);
188 188
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0f241be28f9e..af175166fffa 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -221,11 +221,9 @@ destroy_conntrack(struct nf_conntrack *nfct)
221 * too. */ 221 * too. */
222 nf_ct_remove_expectations(ct); 222 nf_ct_remove_expectations(ct);
223 223
224 /* We overload first tuple to link into unconfirmed list. */ 224 /* We overload first tuple to link into unconfirmed or dying list.*/
225 if (!nf_ct_is_confirmed(ct)) { 225 BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
226 BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 226 hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
227 hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
228 }
229 227
230 NF_CT_STAT_INC(net, delete); 228 NF_CT_STAT_INC(net, delete);
231 spin_unlock_bh(&nf_conntrack_lock); 229 spin_unlock_bh(&nf_conntrack_lock);
@@ -247,6 +245,9 @@ void nf_ct_delete_from_lists(struct nf_conn *ct)
247 * Otherwise we can get spurious warnings. */ 245 * Otherwise we can get spurious warnings. */
248 NF_CT_STAT_INC(net, delete_list); 246 NF_CT_STAT_INC(net, delete_list);
249 clean_from_lists(ct); 247 clean_from_lists(ct);
248 /* add this conntrack to the dying list */
249 hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
250 &net->ct.dying);
250 spin_unlock_bh(&nf_conntrack_lock); 251 spin_unlock_bh(&nf_conntrack_lock);
251} 252}
252EXPORT_SYMBOL_GPL(nf_ct_delete_from_lists); 253EXPORT_SYMBOL_GPL(nf_ct_delete_from_lists);
@@ -268,31 +269,23 @@ static void death_by_event(unsigned long ul_conntrack)
268 } 269 }
269 /* we've got the event delivered, now it's dying */ 270 /* we've got the event delivered, now it's dying */
270 set_bit(IPS_DYING_BIT, &ct->status); 271 set_bit(IPS_DYING_BIT, &ct->status);
271 spin_lock(&nf_conntrack_lock);
272 hlist_nulls_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
273 spin_unlock(&nf_conntrack_lock);
274 nf_ct_put(ct); 272 nf_ct_put(ct);
275} 273}
276 274
277void nf_ct_insert_dying_list(struct nf_conn *ct) 275void nf_ct_dying_timeout(struct nf_conn *ct)
278{ 276{
279 struct net *net = nf_ct_net(ct); 277 struct net *net = nf_ct_net(ct);
280 struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); 278 struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
281 279
282 BUG_ON(ecache == NULL); 280 BUG_ON(ecache == NULL);
283 281
284 /* add this conntrack to the dying list */
285 spin_lock_bh(&nf_conntrack_lock);
286 hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
287 &net->ct.dying);
288 spin_unlock_bh(&nf_conntrack_lock);
289 /* set a new timer to retry event delivery */ 282 /* set a new timer to retry event delivery */
290 setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); 283 setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
291 ecache->timeout.expires = jiffies + 284 ecache->timeout.expires = jiffies +
292 (random32() % net->ct.sysctl_events_retry_timeout); 285 (random32() % net->ct.sysctl_events_retry_timeout);
293 add_timer(&ecache->timeout); 286 add_timer(&ecache->timeout);
294} 287}
295EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); 288EXPORT_SYMBOL_GPL(nf_ct_dying_timeout);
296 289
297static void death_by_timeout(unsigned long ul_conntrack) 290static void death_by_timeout(unsigned long ul_conntrack)
298{ 291{
@@ -307,7 +300,7 @@ static void death_by_timeout(unsigned long ul_conntrack)
307 unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) { 300 unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
308 /* destroy event was not delivered */ 301 /* destroy event was not delivered */
309 nf_ct_delete_from_lists(ct); 302 nf_ct_delete_from_lists(ct);
310 nf_ct_insert_dying_list(ct); 303 nf_ct_dying_timeout(ct);
311 return; 304 return;
312 } 305 }
313 set_bit(IPS_DYING_BIT, &ct->status); 306 set_bit(IPS_DYING_BIT, &ct->status);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 7bbfb3deea30..34370a928360 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -989,7 +989,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
989 nlmsg_report(nlh)) < 0) { 989 nlmsg_report(nlh)) < 0) {
990 nf_ct_delete_from_lists(ct); 990 nf_ct_delete_from_lists(ct);
991 /* we failed to report the event, try later */ 991 /* we failed to report the event, try later */
992 nf_ct_insert_dying_list(ct); 992 nf_ct_dying_timeout(ct);
993 nf_ct_put(ct); 993 nf_ct_put(ct);
994 return 0; 994 return 0;
995 } 995 }