Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / net / netfilter / xt_CT.c
index ae7f5da..bde009e 100644 (file)
@@ -109,7 +109,7 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
        struct xt_ct_target_info *info = par->targinfo;
        struct nf_conntrack_tuple t;
        struct nf_conn *ct;
-       int ret;
+       int ret = -EOPNOTSUPP;
 
        if (info->flags & ~XT_CT_NOTRACK)
                return -EINVAL;
@@ -149,6 +149,10 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
 
        __set_bit(IPS_TEMPLATE_BIT, &ct->status);
        __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+
+       /* Overload tuple linked list to put us in template list. */
+       hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+                                &par->net->ct.tmpl);
 out:
        info->ct = ct;
        return 0;
@@ -243,7 +247,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
        struct xt_ct_target_info_v1 *info = par->targinfo;
        struct nf_conntrack_tuple t;
        struct nf_conn *ct;
-       int ret;
+       int ret = -EOPNOTSUPP;
 
        if (info->flags & ~XT_CT_NOTRACK)
                return -EINVAL;
@@ -289,6 +293,10 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
 
        __set_bit(IPS_TEMPLATE_BIT, &ct->status);
        __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+
+       /* Overload tuple linked list to put us in template list. */
+       hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+                                &par->net->ct.tmpl);
 out:
        info->ct = ct;
        return 0;
@@ -377,14 +385,60 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
        },
 };
 
+static unsigned int
+notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+       /* Previously seen (loopback)? Ignore. */
+       if (skb->nfct != NULL)
+               return XT_CONTINUE;
+
+       skb->nfct = &nf_ct_untracked_get()->ct_general;
+       skb->nfctinfo = IP_CT_NEW;
+       nf_conntrack_get(skb->nfct);
+
+       return XT_CONTINUE;
+}
+
+static int notrack_chk(const struct xt_tgchk_param *par)
+{
+       if (!par->net->xt.notrack_deprecated_warning) {
+               pr_info("netfilter: NOTRACK target is deprecated, "
+                       "use CT instead or upgrade iptables\n");
+               par->net->xt.notrack_deprecated_warning = true;
+       }
+       return 0;
+}
+
+static struct xt_target notrack_tg_reg __read_mostly = {
+       .name           = "NOTRACK",
+       .revision       = 0,
+       .family         = NFPROTO_UNSPEC,
+       .checkentry     = notrack_chk,
+       .target         = notrack_tg,
+       .table          = "raw",
+       .me             = THIS_MODULE,
+};
+
 static int __init xt_ct_tg_init(void)
 {
-       return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
+       int ret;
+
+       ret = xt_register_target(&notrack_tg_reg);
+       if (ret < 0)
+               return ret;
+
+       ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
+       if (ret < 0) {
+               xt_unregister_target(&notrack_tg_reg);
+               return ret;
+       }
+       return 0;
 }
 
 static void __exit xt_ct_tg_exit(void)
 {
        xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
+       xt_unregister_target(&notrack_tg_reg);
 }
 
 module_init(xt_ct_tg_init);
@@ -394,3 +448,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Xtables: connection tracking target");
 MODULE_ALIAS("ipt_CT");
 MODULE_ALIAS("ip6t_CT");
+MODULE_ALIAS("ipt_NOTRACK");
+MODULE_ALIAS("ip6t_NOTRACK");