]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/netfilter/nf_conntrack_core.c
[NETFILTER]: nf_conntrack: sysctl compatibility with old connection tracking
[mirror_ubuntu-bionic-kernel.git] / net / netfilter / nf_conntrack_core.c
index 441a647b784779336121b4197cedf9a43a2ce3e9..a6728067780a747ef4341b0d2ff83e0bf754de4d 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/socket.h>
 
-/* This rwlock protects the main hash table, protocol/helper/expected
-   registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -71,10 +66,12 @@ DEFINE_RWLOCK(nf_conntrack_lock);
 
 /* nf_conntrack_standalone needs this */
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL_GPL(nf_conntrack_count);
 
 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
 unsigned int nf_conntrack_htable_size __read_mostly;
 int nf_conntrack_max __read_mostly;
+EXPORT_SYMBOL_GPL(nf_conntrack_max);
 struct list_head *nf_conntrack_hash __read_mostly;
 struct nf_conn nf_conntrack_untracked __read_mostly;
 unsigned int nf_ct_log_invalid __read_mostly;
@@ -292,7 +289,6 @@ static void
 clean_from_lists(struct nf_conn *ct)
 {
        DEBUGP("clean_from_lists(%p)\n", ct);
-       ASSERT_WRITE_LOCK(&nf_conntrack_lock);
        list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
        list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
 
@@ -371,7 +367,6 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
        struct nf_conntrack_tuple_hash *h;
        unsigned int hash = hash_conntrack(tuple);
 
-       ASSERT_READ_LOCK(&nf_conntrack_lock);
        list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
                if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
                    nf_ct_tuple_equal(tuple, &h->tuple)) {
@@ -871,9 +866,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
                ct->timeout.expires = extra_jiffies;
                event = IPCT_REFRESH;
        } else {
-               /* Need del_timer for race avoidance (may already be dying). */
-               if (del_timer(&ct->timeout)) {
-                       ct->timeout.expires = jiffies + extra_jiffies;
+               unsigned long newtime = jiffies + extra_jiffies;
+
+               /* Only update the timeout if the new timeout is at least
+                  HZ jiffies from the old timeout. Need del_timer for race
+                  avoidance (may already be dying). */
+               if (newtime - ct->timeout.expires >= HZ
+                   && del_timer(&ct->timeout)) {
+                       ct->timeout.expires = newtime;
                        add_timer(&ct->timeout);
                        event = IPCT_REFRESH;
                }
@@ -884,9 +884,10 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
                ct->counters[CTINFO2DIR(ctinfo)].packets++;
                ct->counters[CTINFO2DIR(ctinfo)].bytes +=
                        skb->len - (unsigned int)(skb->nh.raw - skb->data);
-       if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
-           || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
-               event |= IPCT_COUNTER_FILLING;
+
+               if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
+                   || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
+                       event |= IPCT_COUNTER_FILLING;
        }
 #endif
 
@@ -1071,6 +1072,8 @@ void nf_conntrack_cleanup(void)
        free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
                            nf_conntrack_htable_size);
 
+       nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_generic);
+
        /* free l3proto protocol tables */
        for (i = 0; i < PF_MAX; i++)
                if (nf_ct_protos[i]) {
@@ -1196,9 +1199,13 @@ int __init nf_conntrack_init(void)
                goto err_free_conntrack_slab;
        }
 
+       ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_generic);
+       if (ret < 0)
+               goto out_free_expect_slab;
+
        /* Don't NEED lock here, but good form anyway. */
        write_lock_bh(&nf_conntrack_lock);
-        for (i = 0; i < PF_MAX; i++)
+        for (i = 0; i < AF_MAX; i++)
                nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic;
         write_unlock_bh(&nf_conntrack_lock);
 
@@ -1213,6 +1220,8 @@ int __init nf_conntrack_init(void)
 
        return ret;
 
+out_free_expect_slab:
+       kmem_cache_destroy(nf_conntrack_expect_cachep);
 err_free_conntrack_slab:
        nf_conntrack_unregister_cache(NF_CT_F_BASIC);
 err_free_hash: