fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / ipv4 / netfilter / ip_conntrack_standalone.c
index 833fcb4..86efb54 100644 (file)
@@ -12,7 +12,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/ip.h>
 #include <linux/netfilter.h>
 #include <net/ip.h>
 #include <net/route.h>
 
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-#include <linux/netfilter_ipv4/listhelp.h>
 
 #if 0
 #define DEBUGP printk
@@ -141,7 +136,6 @@ static int ct_seq_show(struct seq_file *s, void *v)
        const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
        struct ip_conntrack_protocol *proto;
 
-       ASSERT_READ_LOCK(&ip_conntrack_lock);
        IP_NF_ASSERT(conntrack);
 
        /* we only want to print DIR_ORIGINAL */
@@ -189,6 +183,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
                return -ENOSPC;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+       if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+               return -ENOSPC;
+#endif
+
        if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
                return -ENOSPC;
 
@@ -417,7 +416,7 @@ static unsigned int ip_conntrack_help(unsigned int hooknum,
 
        /* This is where we call the helper: as the packet goes out. */
        ct = ip_conntrack_get(*pskb, &ctinfo);
-       if (ct && ct->helper) {
+       if (ct && ct->helper && ctinfo != IP_CT_RELATED + IP_CT_IS_REPLY) {
                unsigned int ret;
                ret = ct->helper->help(pskb, ct, ctinfo);
                if (ret != NF_ACCEPT)
@@ -469,74 +468,69 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
 
 /* Connection tracking may drop packets, but never alters them, so
    make it the first hook. */
-static struct nf_hook_ops ip_conntrack_defrag_ops = {
-       .hook           = ip_conntrack_defrag,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_PRE_ROUTING,
-       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_in_ops = {
-       .hook           = ip_conntrack_in,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_PRE_ROUTING,
-       .priority       = NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
-       .hook           = ip_conntrack_defrag,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_LOCAL_OUT,
-       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_local_out_ops = {
-       .hook           = ip_conntrack_local,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_LOCAL_OUT,
-       .priority       = NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ip_conntrack_helper_out_ops = {
-       .hook           = ip_conntrack_help,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_POST_ROUTING,
-       .priority       = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ip_conntrack_helper_in_ops = {
-       .hook           = ip_conntrack_help,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_LOCAL_IN,
-       .priority       = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ip_conntrack_out_ops = {
-       .hook           = ip_confirm,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_POST_ROUTING,
-       .priority       = NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ip_conntrack_local_in_ops = {
-       .hook           = ip_confirm,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET,
-       .hooknum        = NF_IP_LOCAL_IN,
-       .priority       = NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ip_conntrack_ops[] = {
+       {
+               .hook           = ip_conntrack_defrag,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_PRE_ROUTING,
+               .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
+       },
+       {
+               .hook           = ip_conntrack_in,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_PRE_ROUTING,
+               .priority       = NF_IP_PRI_CONNTRACK,
+       },
+       {
+               .hook           = ip_conntrack_defrag,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_LOCAL_OUT,
+               .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
+       },
+       {
+               .hook           = ip_conntrack_local,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_LOCAL_OUT,
+               .priority       = NF_IP_PRI_CONNTRACK,
+       },
+       {
+               .hook           = ip_conntrack_help,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_POST_ROUTING,
+               .priority       = NF_IP_PRI_CONNTRACK_HELPER,
+       },
+       {
+               .hook           = ip_conntrack_help,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_LOCAL_IN,
+               .priority       = NF_IP_PRI_CONNTRACK_HELPER,
+       },
+       {
+               .hook           = ip_confirm,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_POST_ROUTING,
+               .priority       = NF_IP_PRI_CONNTRACK_CONFIRM,
+       },
+       {
+               .hook           = ip_confirm,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET,
+               .hooknum        = NF_IP_LOCAL_IN,
+               .priority       = NF_IP_PRI_CONNTRACK_CONFIRM,
+       },
 };
 
 /* Sysctl support */
 
+int ip_conntrack_checksum __read_mostly = 1;
+
 #ifdef CONFIG_SYSCTL
 
 /* From ip_conntrack_core.c */
@@ -564,7 +558,7 @@ extern unsigned int ip_ct_udp_timeout_stream;
 /* From ip_conntrack_proto_icmp.c */
 extern unsigned int ip_ct_icmp_timeout;
 
-/* From ip_conntrack_proto_icmp.c */
+/* From ip_conntrack_proto_generic.c */
 extern unsigned int ip_ct_generic_timeout;
 
 /* Log invalid packets of a given protocol */
@@ -598,6 +592,14 @@ static ctl_table ip_ct_sysctl_table[] = {
                .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_CHECKSUM,
+               .procname       = "ip_conntrack_checksum",
+               .data           = &ip_conntrack_checksum,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
        {
                .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
                .procname       = "ip_conntrack_tcp_timeout_syn_sent",
@@ -783,18 +785,46 @@ static ctl_table ip_ct_net_table[] = {
 EXPORT_SYMBOL(ip_ct_log_invalid);
 #endif /* CONFIG_SYSCTL */
 
-static int init_or_cleanup(int init)
+/* FIXME: Allow NULL functions and sub in pointers to generic for
+   them. --RR */
+int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
+{
+       int ret = 0;
+
+       write_lock_bh(&ip_conntrack_lock);
+       if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+               ret = -EBUSY;
+               goto out;
+       }
+       ip_ct_protos[proto->proto] = proto;
+ out:
+       write_unlock_bh(&ip_conntrack_lock);
+       return ret;
+}
+
+void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
+{
+       write_lock_bh(&ip_conntrack_lock);
+       ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
+       write_unlock_bh(&ip_conntrack_lock);
+
+       /* Somebody could be still looking at the proto in bh. */
+       synchronize_net();
+
+       /* Remove all contrack entries for this protocol */
+       ip_ct_iterate_cleanup(kill_proto, &proto->proto);
+}
+
+static int __init ip_conntrack_standalone_init(void)
 {
 #ifdef CONFIG_PROC_FS
        struct proc_dir_entry *proc, *proc_exp, *proc_stat;
 #endif
        int ret = 0;
 
-       if (!init) goto cleanup;
-
        ret = ip_conntrack_init();
        if (ret < 0)
-               goto cleanup_nothing;
+               return ret;
 
 #ifdef CONFIG_PROC_FS
        ret = -ENOMEM;
@@ -813,78 +843,25 @@ static int init_or_cleanup(int init)
        proc_stat->owner = THIS_MODULE;
 #endif
 
-       ret = nf_register_hook(&ip_conntrack_defrag_ops);
+       ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
        if (ret < 0) {
-               printk("ip_conntrack: can't register pre-routing defrag hook.\n");
+               printk("ip_conntrack: can't register hooks.\n");
                goto cleanup_proc_stat;
        }
-       ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register local_out defrag hook.\n");
-               goto cleanup_defragops;
-       }
-       ret = nf_register_hook(&ip_conntrack_in_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register pre-routing hook.\n");
-               goto cleanup_defraglocalops;
-       }
-       ret = nf_register_hook(&ip_conntrack_local_out_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register local out hook.\n");
-               goto cleanup_inops;
-       }
-       ret = nf_register_hook(&ip_conntrack_helper_in_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register local in helper hook.\n");
-               goto cleanup_inandlocalops;
-       }
-       ret = nf_register_hook(&ip_conntrack_helper_out_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register postrouting helper hook.\n");
-               goto cleanup_helperinops;
-       }
-       ret = nf_register_hook(&ip_conntrack_out_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register post-routing hook.\n");
-               goto cleanup_helperoutops;
-       }
-       ret = nf_register_hook(&ip_conntrack_local_in_ops);
-       if (ret < 0) {
-               printk("ip_conntrack: can't register local in hook.\n");
-               goto cleanup_inoutandlocalops;
-       }
 #ifdef CONFIG_SYSCTL
        ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
        if (ip_ct_sysctl_header == NULL) {
                printk("ip_conntrack: can't register to sysctl.\n");
                ret = -ENOMEM;
-               goto cleanup_localinops;
+               goto cleanup_hooks;
        }
 #endif
-
        return ret;
 
- cleanup:
-       synchronize_net();
 #ifdef CONFIG_SYSCTL
-       unregister_sysctl_table(ip_ct_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+       nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
 #endif
-       nf_unregister_hook(&ip_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
-       nf_unregister_hook(&ip_conntrack_out_ops);
- cleanup_helperoutops:
-       nf_unregister_hook(&ip_conntrack_helper_out_ops);
- cleanup_helperinops:
-       nf_unregister_hook(&ip_conntrack_helper_in_ops);
- cleanup_inandlocalops:
-       nf_unregister_hook(&ip_conntrack_local_out_ops);
- cleanup_inops:
-       nf_unregister_hook(&ip_conntrack_in_ops);
- cleanup_defraglocalops:
-       nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
- cleanup_defragops:
-       nf_unregister_hook(&ip_conntrack_defrag_ops);
  cleanup_proc_stat:
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("ip_conntrack", proc_net_stat);
@@ -895,52 +872,26 @@ static int init_or_cleanup(int init)
  cleanup_init:
 #endif /* CONFIG_PROC_FS */
        ip_conntrack_cleanup();
- cleanup_nothing:
        return ret;
 }
 
-/* FIXME: Allow NULL functions and sub in pointers to generic for
-   them. --RR */
-int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
+static void __exit ip_conntrack_standalone_fini(void)
 {
-       int ret = 0;
-
-       write_lock_bh(&ip_conntrack_lock);
-       if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
-               ret = -EBUSY;
-               goto out;
-       }
-       ip_ct_protos[proto->proto] = proto;
- out:
-       write_unlock_bh(&ip_conntrack_lock);
-       return ret;
-}
-
-void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
-{
-       write_lock_bh(&ip_conntrack_lock);
-       ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
-       write_unlock_bh(&ip_conntrack_lock);
-       
-       /* Somebody could be still looking at the proto in bh. */
        synchronize_net();
-
-       /* Remove all contrack entries for this protocol */
-       ip_ct_iterate_cleanup(kill_proto, &proto->proto);
-}
-
-static int __init init(void)
-{
-       return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
-{
-       init_or_cleanup(0);
+#ifdef CONFIG_SYSCTL
+       unregister_sysctl_table(ip_ct_sysctl_header);
+#endif
+       nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("ip_conntrack", proc_net_stat);
+       proc_net_remove("ip_conntrack_expect");
+       proc_net_remove("ip_conntrack");
+#endif /* CONFIG_PROC_FS */
+       ip_conntrack_cleanup();
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_standalone_init);
+module_exit(ip_conntrack_standalone_fini);
 
 /* Some modules need us, but don't depend directly on any symbol.
    They should call this. */
@@ -971,7 +922,7 @@ EXPORT_SYMBOL(__ip_ct_refresh_acct);
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_put);
 EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
-EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
 EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
@@ -1004,6 +955,7 @@ EXPORT_SYMBOL_GPL(__ip_conntrack_helper_find_byname);
 EXPORT_SYMBOL_GPL(ip_conntrack_proto_find_get);
 EXPORT_SYMBOL_GPL(ip_conntrack_proto_put);
 EXPORT_SYMBOL_GPL(__ip_conntrack_proto_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_checksum);
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
 EXPORT_SYMBOL_GPL(ip_ct_port_tuple_to_nfattr);