]> err.no Git - linux-2.6/blobdiff - net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
Merge git://git.infradead.org/hdrcleanup-2.6
[linux-2.6] / net / ipv6 / netfilter / nf_conntrack_l3proto_ipv6.c
index 704fbbe748746f0657b41c28bade67ad1ce13b7c..2a71c3b669f17993b562cd1875a7b4f04e082b38 100644 (file)
@@ -74,7 +74,7 @@ static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
 static int ipv6_print_tuple(struct seq_file *s,
                            const struct nf_conntrack_tuple *tuple)
 {
-       return seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ",
+       return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ",
                          NIP6(*((struct in6_addr *)tuple->src.u3.ip6)),
                          NIP6(*((struct in6_addr *)tuple->dst.u3.ip6)));
 }
@@ -179,31 +179,36 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
                                 int (*okfn)(struct sk_buff *))
 {
        struct nf_conn *ct;
+       struct nf_conn_help *help;
        enum ip_conntrack_info ctinfo;
+       unsigned int ret, protoff;
+       unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1)
+                             - (*pskb)->data;
+       unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr;
+
 
        /* This is where we call the helper: as the packet goes out. */
        ct = nf_ct_get(*pskb, &ctinfo);
-       if (ct && ct->helper) {
-               unsigned int ret, protoff;
-               unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1)
-                                     - (*pskb)->data;
-               unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr;
-
-               protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
-                                                (*pskb)->len - extoff);
-               if (protoff < 0 || protoff > (*pskb)->len ||
-                   pnum == NEXTHDR_FRAGMENT) {
-                       DEBUGP("proto header not found\n");
-                       return NF_ACCEPT;
-               }
+       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
+               goto out;
+
+       help = nfct_help(ct);
+       if (!help || !help->helper)
+               goto out;
 
-               ret = ct->helper->help(pskb, protoff, ct, ctinfo);
-               if (ret != NF_ACCEPT)
-                       return ret;
+       protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
+                                        (*pskb)->len - extoff);
+       if (protoff < 0 || protoff > (*pskb)->len ||
+           pnum == NEXTHDR_FRAGMENT) {
+               DEBUGP("proto header not found\n");
+               return NF_ACCEPT;
        }
 
+       ret = help->helper->help(pskb, protoff, ct, ctinfo);
+       if (ret != NF_ACCEPT)
+               return ret;
+out:
        /* We've seen it coming out the other side: confirm it */
-
        return nf_conntrack_confirm(pskb);
 }
 
@@ -281,64 +286,58 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
        return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
 }
 
-/* Connection tracking may drop packets, but never alters them, so
-   make it the first hook. */
-static struct nf_hook_ops ipv6_conntrack_defrag_ops = {
-       .hook           = ipv6_defrag,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET6,
-       .hooknum        = NF_IP6_PRE_ROUTING,
-       .priority       = NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv6_conntrack_in_ops = {
-       .hook           = ipv6_conntrack_in,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET6,
-       .hooknum        = NF_IP6_PRE_ROUTING,
-       .priority       = NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_out_ops = {
-       .hook           = ipv6_conntrack_local,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET6,
-       .hooknum        = NF_IP6_LOCAL_OUT,
-       .priority       = NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = {
-       .hook           = ipv6_defrag,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET6,
-       .hooknum        = NF_IP6_LOCAL_OUT,
-       .priority       = NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv6_conntrack_out_ops = {
-       .hook           = ipv6_confirm,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET6,
-       .hooknum        = NF_IP6_POST_ROUTING,
-       .priority       = NF_IP6_PRI_LAST,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
-       .hook           = ipv6_confirm,
-       .owner          = THIS_MODULE,
-       .pf             = PF_INET6,
-       .hooknum        = NF_IP6_LOCAL_IN,
-       .priority       = NF_IP6_PRI_LAST-1,
+static struct nf_hook_ops ipv6_conntrack_ops[] = {
+       {
+               .hook           = ipv6_defrag,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET6,
+               .hooknum        = NF_IP6_PRE_ROUTING,
+               .priority       = NF_IP6_PRI_CONNTRACK_DEFRAG,
+       },
+       {
+               .hook           = ipv6_conntrack_in,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET6,
+               .hooknum        = NF_IP6_PRE_ROUTING,
+               .priority       = NF_IP6_PRI_CONNTRACK,
+       },
+       {
+               .hook           = ipv6_conntrack_local,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET6,
+               .hooknum        = NF_IP6_LOCAL_OUT,
+               .priority       = NF_IP6_PRI_CONNTRACK,
+       },
+       {
+               .hook           = ipv6_defrag,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET6,
+               .hooknum        = NF_IP6_LOCAL_OUT,
+               .priority       = NF_IP6_PRI_CONNTRACK_DEFRAG,
+       },
+       {
+               .hook           = ipv6_confirm,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET6,
+               .hooknum        = NF_IP6_POST_ROUTING,
+               .priority       = NF_IP6_PRI_LAST,
+       },
+       {
+               .hook           = ipv6_confirm,
+               .owner          = THIS_MODULE,
+               .pf             = PF_INET6,
+               .hooknum        = NF_IP6_LOCAL_IN,
+               .priority       = NF_IP6_PRI_LAST-1,
+       },
 };
 
 #ifdef CONFIG_SYSCTL
 
 /* From nf_conntrack_proto_icmpv6.c */
-extern unsigned long nf_ct_icmpv6_timeout;
+extern unsigned int nf_ct_icmpv6_timeout;
 
 /* From nf_conntrack_frag6.c */
-extern unsigned long nf_ct_frag6_timeout;
+extern unsigned int nf_ct_frag6_timeout;
 extern unsigned int nf_ct_frag6_low_thresh;
 extern unsigned int nf_ct_frag6_high_thresh;
 
@@ -465,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
 extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
+
+static int __init nf_conntrack_l3proto_ipv6_init(void)
 {
        int ret = 0;
 
-       if (!init) goto cleanup;
+       need_conntrack();
 
        ret = nf_ct_frag6_init();
        if (ret < 0) {
                printk("nf_conntrack_ipv6: can't initialize frag6.\n");
-               goto cleanup_nothing;
+               return ret;
        }
        ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
        if (ret < 0) {
@@ -500,71 +504,27 @@ static int init_or_cleanup(int init)
                goto cleanup_icmpv6;
        }
 
-       ret = nf_register_hook(&ipv6_conntrack_defrag_ops);
+       ret = nf_register_hooks(ipv6_conntrack_ops,
+                               ARRAY_SIZE(ipv6_conntrack_ops));
        if (ret < 0) {
                printk("nf_conntrack_ipv6: can't register pre-routing defrag "
                       "hook.\n");
                goto cleanup_ipv6;
        }
-
-       ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
-       if (ret < 0) {
-               printk("nf_conntrack_ipv6: can't register local_out defrag "
-                      "hook.\n");
-               goto cleanup_defragops;
-       }
-
-       ret = nf_register_hook(&ipv6_conntrack_in_ops);
-       if (ret < 0) {
-               printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
-               goto cleanup_defraglocalops;
-       }
-
-       ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
-       if (ret < 0) {
-               printk("nf_conntrack_ipv6: can't register local out hook.\n");
-               goto cleanup_inops;
-       }
-
-       ret = nf_register_hook(&ipv6_conntrack_out_ops);
-       if (ret < 0) {
-               printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
-               goto cleanup_inandlocalops;
-       }
-
-       ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
-       if (ret < 0) {
-               printk("nf_conntrack_ipv6: can't register local in hook.\n");
-               goto cleanup_inoutandlocalops;
-       }
-
 #ifdef CONFIG_SYSCTL
        nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
        if (nf_ct_ipv6_sysctl_header == NULL) {
                printk("nf_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(nf_ct_ipv6_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+       nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
 #endif
-       nf_unregister_hook(&ipv6_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
-       nf_unregister_hook(&ipv6_conntrack_out_ops);
- cleanup_inandlocalops:
-       nf_unregister_hook(&ipv6_conntrack_local_out_ops);
- cleanup_inops:
-       nf_unregister_hook(&ipv6_conntrack_in_ops);
- cleanup_defraglocalops:
-       nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
- cleanup_defragops:
-       nf_unregister_hook(&ipv6_conntrack_defrag_ops);
  cleanup_ipv6:
        nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
  cleanup_icmpv6:
@@ -575,29 +535,22 @@ static int init_or_cleanup(int init)
        nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
  cleanup_frag6:
        nf_ct_frag6_cleanup();
- cleanup_nothing:
        return ret;
 }
 
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
-
-static int __init init(void)
-{
-       need_nf_conntrack();
-       return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
-{
-       init_or_cleanup(0);
-}
-
-module_init(init);
-module_exit(fini);
-
-void need_ip6_conntrack(void)
+static void __exit nf_conntrack_l3proto_ipv6_fini(void)
 {
+       synchronize_net();
+#ifdef CONFIG_SYSCTL
+       unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
+#endif
+       nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
+       nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
+       nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
+       nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
+       nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+       nf_ct_frag6_cleanup();
 }
 
-EXPORT_SYMBOL(need_ip6_conntrack);
+module_init(nf_conntrack_l3proto_ipv6_init);
+module_exit(nf_conntrack_l3proto_ipv6_fini);