Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / netfilter / nf_conntrack_helper.c
index 884f2b39319a258ffbaa4360736fd7f83b867195..013cdf69fe29a58ed5b360e6bc59b3d80a916489 100644 (file)
@@ -28,6 +28,7 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_log.h>
 
 static DEFINE_MUTEX(nf_ct_helper_mutex);
 struct hlist_head *nf_ct_helper_hash __read_mostly;
@@ -236,7 +237,9 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                /* We only allow helper re-assignment of the same sort since
                 * we cannot reallocate the helper extension area.
                 */
-               if (help->helper != helper) {
+               struct nf_conntrack_helper *tmp = rcu_dereference(help->helper);
+
+               if (tmp && tmp->help != helper->help) {
                        RCU_INIT_POINTER(help->helper, NULL);
                        goto out;
                }
@@ -332,6 +335,24 @@ nf_ct_helper_expectfn_find_by_symbol(const void *symbol)
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
 
+__printf(3, 4)
+void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
+                     const char *fmt, ...)
+{
+       const struct nf_conn_help *help;
+       const struct nf_conntrack_helper *helper;
+
+       /* Called from the helper function, this call never fails */
+       help = nfct_help(ct);
+
+       /* rcu_read_lock()ed by nf_hook_slow */
+       helper = rcu_dereference(help->helper);
+
+       nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL,
+                     "nf_ct_%s: dropping packet: %s ", helper->name, fmt);
+}
+EXPORT_SYMBOL_GPL(nf_ct_helper_log);
+
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
        int ret = 0;
@@ -423,44 +444,41 @@ static struct nf_ct_ext_type helper_extend __read_mostly = {
        .id     = NF_CT_EXT_HELPER,
 };
 
-int nf_conntrack_helper_init(struct net *net)
+int nf_conntrack_helper_pernet_init(struct net *net)
 {
-       int err;
-
        net->ct.auto_assign_helper_warned = false;
        net->ct.sysctl_auto_assign_helper = nf_ct_auto_assign_helper;
+       return nf_conntrack_helper_init_sysctl(net);
+}
 
-       if (net_eq(net, &init_net)) {
-               nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
-               nf_ct_helper_hash =
-                       nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0);
-               if (!nf_ct_helper_hash)
-                       return -ENOMEM;
+void nf_conntrack_helper_pernet_fini(struct net *net)
+{
+       nf_conntrack_helper_fini_sysctl(net);
+}
 
-               err = nf_ct_extend_register(&helper_extend);
-               if (err < 0)
-                       goto err1;
+int nf_conntrack_helper_init(void)
+{
+       int ret;
+       nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
+       nf_ct_helper_hash =
+               nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0);
+       if (!nf_ct_helper_hash)
+               return -ENOMEM;
+
+       ret = nf_ct_extend_register(&helper_extend);
+       if (ret < 0) {
+               pr_err("nf_ct_helper: Unable to register helper extension.\n");
+               goto out_extend;
        }
 
-       err = nf_conntrack_helper_init_sysctl(net);
-       if (err < 0)
-               goto out_sysctl;
-
        return 0;
-
-out_sysctl:
-       if (net_eq(net, &init_net))
-               nf_ct_extend_unregister(&helper_extend);
-err1:
+out_extend:
        nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
-       return err;
+       return ret;
 }
 
-void nf_conntrack_helper_fini(struct net *net)
+void nf_conntrack_helper_fini(void)
 {
-       nf_conntrack_helper_fini_sysctl(net);
-       if (net_eq(net, &init_net)) {
-               nf_ct_extend_unregister(&helper_extend);
-               nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
-       }
+       nf_ct_extend_unregister(&helper_extend);
+       nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
 }