summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/transp_v6.h12
-rw-r--r--net/ipv6/af_inet6.c77
-rw-r--r--net/ipv6/ipv6_sockglue.c3
-rw-r--r--net/ipv6/raw.c52
-rw-r--r--net/ipv6/tcp_ipv6.c36
-rw-r--r--net/ipv6/udp.c26
-rw-r--r--net/ipv6/udplite.c25
8 files changed, 168 insertions, 65 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4d910658095..f2adedff927 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -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);
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index aa9a4a6b99d..27394e0447d 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -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,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 53b06de696b..34c20533ba5 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -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
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 8c5f80fd03a..20fece4ad3d 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -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)
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index b34631e1b01..850b83e430b 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -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);
+}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 93980c3b83e..9544beb6d1c 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -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);
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index fa640765385..1e3bd39f54e 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -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);
}
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index 5a0379f7141..f20b376689f 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -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