Commit 7f4e4868 authored by Daniel Lezcano's avatar Daniel Lezcano Committed by David S. Miller

[IPV6]: make the protocol initialization to return an error code

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: default avatarDaniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 87c3efbf
...@@ -545,7 +545,7 @@ extern int compat_ipv6_getsockopt(struct sock *sk, ...@@ -545,7 +545,7 @@ extern int compat_ipv6_getsockopt(struct sock *sk,
char __user *optval, char __user *optval,
int __user *optlen); int __user *optlen);
extern void ipv6_packet_init(void); extern int ipv6_packet_init(void);
extern void ipv6_packet_cleanup(void); extern void ipv6_packet_cleanup(void);
......
...@@ -23,10 +23,14 @@ extern int ipv6_frag_init(void); ...@@ -23,10 +23,14 @@ extern int ipv6_frag_init(void);
extern void ipv6_frag_exit(void); extern void ipv6_frag_exit(void);
/* transport protocols */ /* transport protocols */
extern void rawv6_init(void); extern int rawv6_init(void);
extern void udpv6_init(void); extern void rawv6_exit(void);
extern void udplitev6_init(void); extern int udpv6_init(void);
extern void tcpv6_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, extern int udpv6_connect(struct sock *sk,
struct sockaddr *uaddr, struct sockaddr *uaddr,
......
...@@ -529,42 +529,6 @@ static struct net_proto_family inet6_family_ops = { ...@@ -529,42 +529,6 @@ static struct net_proto_family inet6_family_ops = {
.owner = THIS_MODULE, .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) int inet6_register_protosw(struct inet_protosw *p)
{ {
struct list_head *lh; struct list_head *lh;
...@@ -771,7 +735,6 @@ static int __init inet6_init(void) ...@@ -771,7 +735,6 @@ static int __init inet6_init(void)
__this_module.can_unload = &ipv6_unload; __this_module.can_unload = &ipv6_unload;
#endif #endif
#endif #endif
err = proto_register(&tcpv6_prot, 1); err = proto_register(&tcpv6_prot, 1);
if (err) if (err)
goto out; goto out;
...@@ -796,14 +759,16 @@ static int __init inet6_init(void) ...@@ -796,14 +759,16 @@ static int __init inet6_init(void)
/* We MUST register RAW sockets before we create the ICMP6, /* We MUST register RAW sockets before we create the ICMP6,
* IGMP6, or NDISC control sockets. * 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 /* Register the family here so that the init calls below will
* be able to create sockets. (?? is this dangerous ??) * be able to create sockets. (?? is this dangerous ??)
*/ */
err = sock_register(&inet6_family_ops); err = sock_register(&inet6_family_ops);
if (err) if (err)
goto out_unregister_raw_proto; goto out_sock_register_fail;
/* Initialise ipv6 mibs */ /* Initialise ipv6 mibs */
err = init_ipv6_mibs(); err = init_ipv6_mibs();
...@@ -871,15 +836,32 @@ static int __init inet6_init(void) ...@@ -871,15 +836,32 @@ static int __init inet6_init(void)
goto ipv6_frag_fail; goto ipv6_frag_fail;
/* Init v6 transport protocols. */ /* Init v6 transport protocols. */
udpv6_init(); err = udpv6_init();
udplitev6_init(); if (err)
tcpv6_init(); goto udpv6_fail;
ipv6_packet_init(); err = udplitev6_init();
err = 0; if (err)
goto udplitev6_fail;
err = tcpv6_init();
if (err)
goto tcpv6_fail;
err = ipv6_packet_init();
if (err)
goto ipv6_packet_fail;
out: out:
return err; return err;
ipv6_packet_fail:
tcpv6_exit();
tcpv6_fail:
udplitev6_exit();
udplitev6_fail:
udpv6_exit();
udpv6_fail:
ipv6_frag_exit();
ipv6_frag_fail: ipv6_frag_fail:
ipv6_exthdrs_exit(); ipv6_exthdrs_exit();
ipv6_exthdrs_fail: ipv6_exthdrs_fail:
...@@ -920,6 +902,8 @@ icmp_fail: ...@@ -920,6 +902,8 @@ icmp_fail:
out_unregister_sock: out_unregister_sock:
sock_unregister(PF_INET6); sock_unregister(PF_INET6);
rtnl_unregister_all(PF_INET6); rtnl_unregister_all(PF_INET6);
out_sock_register_fail:
rawv6_exit();
out_unregister_raw_proto: out_unregister_raw_proto:
proto_unregister(&rawv6_prot); proto_unregister(&rawv6_prot);
out_unregister_udplite_proto: out_unregister_udplite_proto:
...@@ -939,6 +923,10 @@ static void __exit inet6_exit(void) ...@@ -939,6 +923,10 @@ static void __exit inet6_exit(void)
/* Disallow any further netlink messages */ /* Disallow any further netlink messages */
rtnl_unregister_all(PF_INET6); rtnl_unregister_all(PF_INET6);
udpv6_exit();
udplitev6_exit();
tcpv6_exit();
/* Cleanup code parts. */ /* Cleanup code parts. */
ipv6_packet_cleanup(); ipv6_packet_cleanup();
ipv6_frag_exit(); ipv6_frag_exit();
...@@ -961,6 +949,7 @@ static void __exit inet6_exit(void) ...@@ -961,6 +949,7 @@ static void __exit inet6_exit(void)
igmp6_cleanup(); igmp6_cleanup();
ndisc_cleanup(); ndisc_cleanup();
icmpv6_cleanup(); icmpv6_cleanup();
rawv6_exit();
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
ipv6_sysctl_unregister(); ipv6_sysctl_unregister();
#endif #endif
......
...@@ -1128,9 +1128,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, ...@@ -1128,9 +1128,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
EXPORT_SYMBOL(compat_ipv6_getsockopt); EXPORT_SYMBOL(compat_ipv6_getsockopt);
#endif #endif
void __init ipv6_packet_init(void) int __init ipv6_packet_init(void)
{ {
dev_add_pack(&ipv6_packet_type); dev_add_pack(&ipv6_packet_type);
return 0;
} }
void ipv6_packet_cleanup(void) void ipv6_packet_cleanup(void)
......
...@@ -1273,3 +1273,55 @@ void raw6_proc_exit(void) ...@@ -1273,3 +1273,55 @@ void raw6_proc_exit(void)
proc_net_remove(&init_net, "raw6"); proc_net_remove(&init_net, "raw6");
} }
#endif /* CONFIG_PROC_FS */ #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);
}
...@@ -2166,14 +2166,36 @@ static struct inet_protosw tcpv6_protosw = { ...@@ -2166,14 +2166,36 @@ static struct inet_protosw tcpv6_protosw = {
INET_PROTOSW_ICSK, 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 */ /* register inet6 protocol */
if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0) ret = inet6_register_protosw(&tcpv6_protosw);
printk(KERN_ERR "tcpv6_init: Could not register protocol\n"); if (ret)
inet6_register_protosw(&tcpv6_protosw); 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, out_tcpv6_protocol:
IPPROTO_TCP) < 0) inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
panic("Failed to create the TCPv6 control socket.\n"); 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);
} }
...@@ -1016,9 +1016,27 @@ static struct inet_protosw udpv6_protosw = { ...@@ -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) int ret;
printk(KERN_ERR "udpv6_init: Could not register protocol\n");
inet6_register_protosw(&udpv6_protosw); 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);
} }
...@@ -77,12 +77,29 @@ static struct inet_protosw udplite6_protosw = { ...@@ -77,12 +77,29 @@ static struct inet_protosw udplite6_protosw = {
.flags = INET_PROTOSW_PERMANENT, .flags = INET_PROTOSW_PERMANENT,
}; };
void __init udplitev6_init(void) int __init udplitev6_init(void)
{ {
if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0) int ret;
printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__);
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 #ifdef CONFIG_PROC_FS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment