[IPV6]: make the protocol initialization to return an error code
authorDaniel Lezcano <dlezcano@fr.ibm.com>
Tue, 11 Dec 2007 10:25:35 +0000 (02:25 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:57:13 +0000 (14:57 -0800)
This patchset makes the different protocols to return an error code, so
the af_inet6 module can check the initialization was correct or not.

The raw6 was taken into account to be consistent with the rest of the
protocols, but the registration is at the same place.
Because the raw6 has its own init function, the proto and the ops structure
can be moved inside the raw6.c file.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ipv6.h
include/net/transp_v6.h
net/ipv6/af_inet6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/raw.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udplite.c

index 4d9106580950b58813f7111937055831992fe71b..f2adedff927fcc8a106938d3ee62600092f636ad 100644 (file)
@@ -545,7 +545,7 @@ extern int                  compat_ipv6_getsockopt(struct sock *sk,
                                                char __user *optval,
                                                int __user *optlen);
 
-extern void                    ipv6_packet_init(void);
+extern int                     ipv6_packet_init(void);
 
 extern void                    ipv6_packet_cleanup(void);
 
index aa9a4a6b99df03cdb87fb81b00e81ec0ca32a805..27394e0447d88d9b5d788b14b8e4bed582b45817 100644 (file)
@@ -23,10 +23,14 @@ extern int                          ipv6_frag_init(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,
index 53b06de696bd78709d2367e2e6a68b6e8a75670d..34c20533ba5d972bf3d8adf7384a5a51075e0261 100644 (file)
@@ -529,42 +529,6 @@ static struct net_proto_family inet6_family_ops = {
        .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;
@@ -771,7 +735,6 @@ static int __init inet6_init(void)
        __this_module.can_unload = &ipv6_unload;
 #endif
 #endif
-
        err = proto_register(&tcpv6_prot, 1);
        if (err)
                goto out;
@@ -796,14 +759,16 @@ static int __init inet6_init(void)
        /* 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();
@@ -871,15 +836,32 @@ static int __init inet6_init(void)
                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:
@@ -920,6 +902,8 @@ icmp_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:
@@ -939,6 +923,10 @@ static void __exit inet6_exit(void)
        /* 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();
@@ -961,6 +949,7 @@ static void __exit inet6_exit(void)
        igmp6_cleanup();
        ndisc_cleanup();
        icmpv6_cleanup();
+       rawv6_exit();
 #ifdef CONFIG_SYSCTL
        ipv6_sysctl_unregister();
 #endif
index 8c5f80fd03ada72af490ad8786a3e492a48d3c8c..20fece4ad3d8aaaca575d22a42330b62432304c4 100644 (file)
@@ -1128,9 +1128,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
 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)
index b34631e1b015c080553cec4ea3f16224c781d30f..850b83e430bc5482bd2f66609f8c06c3e08fa773 100644 (file)
@@ -1273,3 +1273,55 @@ void raw6_proc_exit(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);
+}
index 93980c3b83e694460fe42ab4ed74e91f47649d2f..9544beb6d1ca1abc3a04d00f2f54380b87781d2d 100644 (file)
@@ -2166,14 +2166,36 @@ static struct inet_protosw tcpv6_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);
 }
index fa640765385e995350a4dc2a1fe9b4c19552ea3b..1e3bd39f54ecadbda99576f17e936b66864b3498 100644 (file)
@@ -1016,9 +1016,27 @@ static struct inet_protosw udpv6_protosw = {
 };
 
 
-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);
 }
index 5a0379f7141515f2ddc1841959ecde05f8a3ee66..f20b376689fb62b39ead25d7b319aa82d3431ceb 100644 (file)
@@ -77,12 +77,29 @@ static struct inet_protosw udplite6_protosw = {
        .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