Merge tag 'v3.10.99' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / netfilter / nf_conntrack_core.c
index fae881e8b8ef0e0d3e51a2456712c11ee3b05b02..97248f8b266562d12501307b508fbc247a0c1b28 100644 (file)
@@ -311,6 +311,21 @@ static void death_by_timeout(unsigned long ul_conntrack)
        nf_ct_put(ct);
 }
 
+static inline bool
+nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
+                       const struct nf_conntrack_tuple *tuple,
+                       u16 zone)
+{
+       struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+
+       /* A conntrack can be recreated with the equal tuple,
+        * so we need to check that the conntrack is confirmed
+        */
+       return nf_ct_tuple_equal(tuple, &h->tuple) &&
+               nf_ct_zone(ct) == zone &&
+               nf_ct_is_confirmed(ct);
+}
+
 /*
  * Warning :
  * - Caller must take a reference on returned object
@@ -332,8 +347,7 @@ ____nf_conntrack_find(struct net *net, u16 zone,
        local_bh_disable();
 begin:
        hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) {
-               if (nf_ct_tuple_equal(tuple, &h->tuple) &&
-                   nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {
+               if (nf_ct_key_equal(h, tuple, zone)) {
                        NF_CT_STAT_INC(net, found);
                        local_bh_enable();
                        return h;
@@ -380,8 +394,7 @@ begin:
                             !atomic_inc_not_zero(&ct->ct_general.use)))
                        h = NULL;
                else {
-                       if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) ||
-                                    nf_ct_zone(ct) != zone)) {
+                       if (unlikely(!nf_ct_key_equal(h, tuple, zone))) {
                                nf_ct_put(ct);
                                goto begin;
                        }