char __user *optval,
                                                int __user *optlen);
 
-extern void                    ipv6_packet_init(void);
+extern int                     ipv6_packet_init(void);
 
 extern void                    ipv6_packet_cleanup(void);
 
 
 extern void                            ipv6_frag_exit(void);
 
 /* transport protocols */
-extern void                            rawv6_init(void);
-extern void                            udpv6_init(void);
-extern void                            udplitev6_init(void);
-extern void                            tcpv6_init(void);
+extern int                             rawv6_init(void);
+extern void                            rawv6_exit(void);
+extern int                             udpv6_init(void);
+extern void                            udpv6_exit(void);
+extern int                             udplitev6_init(void);
+extern void                            udplitev6_exit(void);
+extern int                             tcpv6_init(void);
+extern void                            tcpv6_exit(void);
 
 extern int                             udpv6_connect(struct sock *sk,
                                                      struct sockaddr *uaddr,
 
        .owner  = THIS_MODULE,
 };
 
-/* Same as inet6_dgram_ops, sans udp_poll.  */
-static const struct proto_ops inet6_sockraw_ops = {
-       .family            = PF_INET6,
-       .owner             = THIS_MODULE,
-       .release           = inet6_release,
-       .bind              = inet6_bind,
-       .connect           = inet_dgram_connect,        /* ok           */
-       .socketpair        = sock_no_socketpair,        /* a do nothing */
-       .accept            = sock_no_accept,            /* a do nothing */
-       .getname           = inet6_getname,
-       .poll              = datagram_poll,             /* ok           */
-       .ioctl             = inet6_ioctl,               /* must change  */
-       .listen            = sock_no_listen,            /* ok           */
-       .shutdown          = inet_shutdown,             /* ok           */
-       .setsockopt        = sock_common_setsockopt,    /* ok           */
-       .getsockopt        = sock_common_getsockopt,    /* ok           */
-       .sendmsg           = inet_sendmsg,              /* ok           */
-       .recvmsg           = sock_common_recvmsg,       /* ok           */
-       .mmap              = sock_no_mmap,
-       .sendpage          = sock_no_sendpage,
-#ifdef CONFIG_COMPAT
-       .compat_setsockopt = compat_sock_common_setsockopt,
-       .compat_getsockopt = compat_sock_common_getsockopt,
-#endif
-};
-
-static struct inet_protosw rawv6_protosw = {
-       .type           = SOCK_RAW,
-       .protocol       = IPPROTO_IP,   /* wild card */
-       .prot           = &rawv6_prot,
-       .ops            = &inet6_sockraw_ops,
-       .capability     = CAP_NET_RAW,
-       .no_check       = UDP_CSUM_DEFAULT,
-       .flags          = INET_PROTOSW_REUSE,
-};
-
 int inet6_register_protosw(struct inet_protosw *p)
 {
        struct list_head *lh;
        __this_module.can_unload = &ipv6_unload;
 #endif
 #endif
-
        err = proto_register(&tcpv6_prot, 1);
        if (err)
                goto out;
        /* We MUST register RAW sockets before we create the ICMP6,
         * IGMP6, or NDISC control sockets.
         */
-       inet6_register_protosw(&rawv6_protosw);
+       err = rawv6_init();
+       if (err)
+               goto out_unregister_raw_proto;
 
        /* Register the family here so that the init calls below will
         * be able to create sockets. (?? is this dangerous ??)
         */
        err = sock_register(&inet6_family_ops);
        if (err)
-               goto out_unregister_raw_proto;
+               goto out_sock_register_fail;
 
        /* Initialise ipv6 mibs */
        err = init_ipv6_mibs();
                goto ipv6_frag_fail;
 
        /* Init v6 transport protocols. */
-       udpv6_init();
-       udplitev6_init();
-       tcpv6_init();
+       err = udpv6_init();
+       if (err)
+               goto udpv6_fail;
 
-       ipv6_packet_init();
-       err = 0;
+       err = udplitev6_init();
+       if (err)
+               goto udplitev6_fail;
+
+       err = tcpv6_init();
+       if (err)
+               goto tcpv6_fail;
+
+       err = ipv6_packet_init();
+       if (err)
+               goto ipv6_packet_fail;
 out:
        return err;
 
+ipv6_packet_fail:
+       tcpv6_exit();
+tcpv6_fail:
+       udplitev6_exit();
+udplitev6_fail:
+       udpv6_exit();
+udpv6_fail:
+       ipv6_frag_exit();
 ipv6_frag_fail:
        ipv6_exthdrs_exit();
 ipv6_exthdrs_fail:
 out_unregister_sock:
        sock_unregister(PF_INET6);
        rtnl_unregister_all(PF_INET6);
+out_sock_register_fail:
+       rawv6_exit();
 out_unregister_raw_proto:
        proto_unregister(&rawv6_prot);
 out_unregister_udplite_proto:
        /* Disallow any further netlink messages */
        rtnl_unregister_all(PF_INET6);
 
+       udpv6_exit();
+       udplitev6_exit();
+       tcpv6_exit();
+
        /* Cleanup code parts. */
        ipv6_packet_cleanup();
        ipv6_frag_exit();
        igmp6_cleanup();
        ndisc_cleanup();
        icmpv6_cleanup();
+       rawv6_exit();
 #ifdef CONFIG_SYSCTL
        ipv6_sysctl_unregister();
 #endif
 
 EXPORT_SYMBOL(compat_ipv6_getsockopt);
 #endif
 
-void __init ipv6_packet_init(void)
+int __init ipv6_packet_init(void)
 {
        dev_add_pack(&ipv6_packet_type);
+       return 0;
 }
 
 void ipv6_packet_cleanup(void)
 
        proc_net_remove(&init_net, "raw6");
 }
 #endif /* CONFIG_PROC_FS */
+
+/* Same as inet6_dgram_ops, sans udp_poll.  */
+static const struct proto_ops inet6_sockraw_ops = {
+       .family            = PF_INET6,
+       .owner             = THIS_MODULE,
+       .release           = inet6_release,
+       .bind              = inet6_bind,
+       .connect           = inet_dgram_connect,        /* ok           */
+       .socketpair        = sock_no_socketpair,        /* a do nothing */
+       .accept            = sock_no_accept,            /* a do nothing */
+       .getname           = inet6_getname,
+       .poll              = datagram_poll,             /* ok           */
+       .ioctl             = inet6_ioctl,               /* must change  */
+       .listen            = sock_no_listen,            /* ok           */
+       .shutdown          = inet_shutdown,             /* ok           */
+       .setsockopt        = sock_common_setsockopt,    /* ok           */
+       .getsockopt        = sock_common_getsockopt,    /* ok           */
+       .sendmsg           = inet_sendmsg,              /* ok           */
+       .recvmsg           = sock_common_recvmsg,       /* ok           */
+       .mmap              = sock_no_mmap,
+       .sendpage          = sock_no_sendpage,
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt = compat_sock_common_setsockopt,
+       .compat_getsockopt = compat_sock_common_getsockopt,
+#endif
+};
+
+static struct inet_protosw rawv6_protosw = {
+       .type           = SOCK_RAW,
+       .protocol       = IPPROTO_IP,   /* wild card */
+       .prot           = &rawv6_prot,
+       .ops            = &inet6_sockraw_ops,
+       .capability     = CAP_NET_RAW,
+       .no_check       = UDP_CSUM_DEFAULT,
+       .flags          = INET_PROTOSW_REUSE,
+};
+
+int __init rawv6_init(void)
+{
+       int ret;
+
+       ret = inet6_register_protosw(&rawv6_protosw);
+       if (ret)
+               goto out;
+out:
+       return ret;
+}
+
+void __exit rawv6_exit(void)
+{
+       inet6_unregister_protosw(&rawv6_protosw);
+}
 
                                INET_PROTOSW_ICSK,
 };
 
-void __init tcpv6_init(void)
+int __init tcpv6_init(void)
 {
+       int ret;
+
+       ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
+       if (ret)
+               goto out;
+
        /* register inet6 protocol */
-       if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0)
-               printk(KERN_ERR "tcpv6_init: Could not register protocol\n");
-       inet6_register_protosw(&tcpv6_protosw);
+       ret = inet6_register_protosw(&tcpv6_protosw);
+       if (ret)
+               goto out_tcpv6_protocol;
+
+       ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6,
+                                      SOCK_RAW, IPPROTO_TCP);
+       if (ret)
+               goto out_tcpv6_protosw;
+out:
+       return ret;
 
-       if (inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, SOCK_RAW,
-                                    IPPROTO_TCP) < 0)
-               panic("Failed to create the TCPv6 control socket.\n");
+out_tcpv6_protocol:
+       inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
+out_tcpv6_protosw:
+       inet6_unregister_protosw(&tcpv6_protosw);
+       goto out;
+}
+
+void __exit tcpv6_exit(void)
+{
+       sock_release(tcp6_socket);
+       inet6_unregister_protosw(&tcpv6_protosw);
+       inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 }
 
 };
 
 
-void __init udpv6_init(void)
+int __init udpv6_init(void)
 {
-       if (inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP) < 0)
-               printk(KERN_ERR "udpv6_init: Could not register protocol\n");
-       inet6_register_protosw(&udpv6_protosw);
+       int ret;
+
+       ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
+       if (ret)
+               goto out;
+
+       ret = inet6_register_protosw(&udpv6_protosw);
+       if (ret)
+               goto out_udpv6_protocol;
+out:
+       return ret;
+
+out_udpv6_protocol:
+       inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
+       goto out;
+}
+
+void __exit udpv6_exit(void)
+{
+       inet6_unregister_protosw(&udpv6_protosw);
+       inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
 }
 
        .flags          = INET_PROTOSW_PERMANENT,
 };
 
-void __init udplitev6_init(void)
+int __init udplitev6_init(void)
 {
-       if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0)
-               printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__);
+       int ret;
 
-       inet6_register_protosw(&udplite6_protosw);
+       ret = inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
+       if (ret)
+               goto out;
+
+       ret = inet6_register_protosw(&udplite6_protosw);
+       if (ret)
+               goto out_udplitev6_protocol;
+out:
+       return ret;
+
+out_udplitev6_protocol:
+       inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
+       goto out;
+}
+
+void __exit udplitev6_exit(void)
+{
+       inet6_unregister_protosw(&udplite6_protosw);
+       inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
 }
 
 #ifdef CONFIG_PROC_FS