OSDN Git Service

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[uclinux-h8/linux.git] / net / ipv6 / netfilter / ip6table_mangle.c
index abe278b..cb2b288 100644 (file)
@@ -23,12 +23,15 @@ MODULE_DESCRIPTION("ip6tables mangle table");
                            (1 << NF_INET_LOCAL_OUT) | \
                            (1 << NF_INET_POST_ROUTING))
 
+static int __net_init ip6table_mangle_table_init(struct net *net);
+
 static const struct xt_table packet_mangler = {
        .name           = "mangle",
        .valid_hooks    = MANGLE_VALID_HOOKS,
        .me             = THIS_MODULE,
        .af             = NFPROTO_IPV6,
        .priority       = NF_IP6_PRI_MANGLE,
+       .table_init     = ip6table_mangle_table_init,
 };
 
 static unsigned int
@@ -88,26 +91,33 @@ ip6table_mangle_hook(void *priv, struct sk_buff *skb,
 }
 
 static struct nf_hook_ops *mangle_ops __read_mostly;
-static int __net_init ip6table_mangle_net_init(struct net *net)
+static int __net_init ip6table_mangle_table_init(struct net *net)
 {
        struct ip6t_replace *repl;
+       int ret;
+
+       if (net->ipv6.ip6table_mangle)
+               return 0;
 
        repl = ip6t_alloc_initial_table(&packet_mangler);
        if (repl == NULL)
                return -ENOMEM;
-       net->ipv6.ip6table_mangle =
-               ip6t_register_table(net, &packet_mangler, repl);
+       ret = ip6t_register_table(net, &packet_mangler, repl, mangle_ops,
+                                 &net->ipv6.ip6table_mangle);
        kfree(repl);
-       return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle);
+       return ret;
 }
 
 static void __net_exit ip6table_mangle_net_exit(struct net *net)
 {
-       ip6t_unregister_table(net, net->ipv6.ip6table_mangle);
+       if (!net->ipv6.ip6table_mangle)
+               return;
+
+       ip6t_unregister_table(net, net->ipv6.ip6table_mangle, mangle_ops);
+       net->ipv6.ip6table_mangle = NULL;
 }
 
 static struct pernet_operations ip6table_mangle_net_ops = {
-       .init = ip6table_mangle_net_init,
        .exit = ip6table_mangle_net_exit,
 };
 
@@ -115,28 +125,28 @@ static int __init ip6table_mangle_init(void)
 {
        int ret;
 
+       mangle_ops = xt_hook_ops_alloc(&packet_mangler, ip6table_mangle_hook);
+       if (IS_ERR(mangle_ops))
+               return PTR_ERR(mangle_ops);
+
        ret = register_pernet_subsys(&ip6table_mangle_net_ops);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(mangle_ops);
                return ret;
-
-       /* Register hooks */
-       mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
-       if (IS_ERR(mangle_ops)) {
-               ret = PTR_ERR(mangle_ops);
-               goto cleanup_table;
        }
 
-       return ret;
-
- cleanup_table:
-       unregister_pernet_subsys(&ip6table_mangle_net_ops);
+       ret = ip6table_mangle_table_init(&init_net);
+       if (ret) {
+               unregister_pernet_subsys(&ip6table_mangle_net_ops);
+               kfree(mangle_ops);
+       }
        return ret;
 }
 
 static void __exit ip6table_mangle_fini(void)
 {
-       xt_hook_unlink(&packet_mangler, mangle_ops);
        unregister_pernet_subsys(&ip6table_mangle_net_ops);
+       kfree(mangle_ops);
 }
 
 module_init(ip6table_mangle_init);