diff options
author | Daniel Lezcano <dlezcano@fr.ibm.com> | 2008-03-07 14:16:02 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-07 14:16:02 -0500 |
commit | 93ec926b075d14bb7edcbc054e92199e9ad4ad1d (patch) | |
tree | 7899be4a1f6e45199e80a324a9e9af8b582b5fb3 /net | |
parent | 1762f7e88eb34f653b4a915be99a102e347dd45e (diff) |
[NETNS][IPV6] tcp6 - make socket control per namespace
Instead of having a tcp6_socket global to all the namespace, there is
tcp6 socket control per namespace. That is consistent with which
namespace sent a RST and allows to pass the socket to the underlying
function to retrieve the network namespace.
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b47cce8fea44..7954b4e99c4f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -69,9 +69,6 @@ | |||
69 | #include <linux/crypto.h> | 69 | #include <linux/crypto.h> |
70 | #include <linux/scatterlist.h> | 70 | #include <linux/scatterlist.h> |
71 | 71 | ||
72 | /* Socket used for sending RSTs and ACKs */ | ||
73 | static struct socket *tcp6_socket; | ||
74 | |||
75 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); | 72 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); |
76 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); | 73 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); |
77 | static void tcp_v6_send_check(struct sock *sk, int len, | 74 | static void tcp_v6_send_check(struct sock *sk, int len, |
@@ -1075,10 +1072,11 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1075 | * Underlying function will use this to retrieve the network | 1072 | * Underlying function will use this to retrieve the network |
1076 | * namespace | 1073 | * namespace |
1077 | */ | 1074 | */ |
1078 | if (!ip6_dst_lookup(tcp6_socket->sk, &buff->dst, &fl)) { | 1075 | if (!ip6_dst_lookup(init_net.ipv6.tcp_sk, &buff->dst, &fl)) { |
1079 | 1076 | ||
1080 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1077 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1081 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1078 | ip6_xmit(init_net.ipv6.tcp_sk, |
1079 | buff, &fl, NULL, 0); | ||
1082 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1080 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1083 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); | 1081 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); |
1084 | return; | 1082 | return; |
@@ -1175,9 +1173,10 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1175 | fl.fl_ip_sport = t1->source; | 1173 | fl.fl_ip_sport = t1->source; |
1176 | security_skb_classify_flow(skb, &fl); | 1174 | security_skb_classify_flow(skb, &fl); |
1177 | 1175 | ||
1178 | if (!ip6_dst_lookup(tcp6_socket->sk, &buff->dst, &fl)) { | 1176 | if (!ip6_dst_lookup(init_net.ipv6.tcp_sk, &buff->dst, &fl)) { |
1179 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1177 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1180 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1178 | ip6_xmit(init_net.ipv6.tcp_sk, |
1179 | buff, &fl, NULL, 0); | ||
1181 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1180 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1182 | return; | 1181 | return; |
1183 | } | 1182 | } |
@@ -2198,6 +2197,31 @@ static struct inet_protosw tcpv6_protosw = { | |||
2198 | INET_PROTOSW_ICSK, | 2197 | INET_PROTOSW_ICSK, |
2199 | }; | 2198 | }; |
2200 | 2199 | ||
2200 | static int tcpv6_net_init(struct net *net) | ||
2201 | { | ||
2202 | int err; | ||
2203 | struct socket *sock; | ||
2204 | struct sock *sk; | ||
2205 | |||
2206 | err = inet_csk_ctl_sock_create(&sock, PF_INET6, SOCK_RAW, IPPROTO_TCP); | ||
2207 | if (err) | ||
2208 | return err; | ||
2209 | |||
2210 | net->ipv6.tcp_sk = sk = sock->sk; | ||
2211 | sk_change_net(sk, net); | ||
2212 | return err; | ||
2213 | } | ||
2214 | |||
2215 | static void tcpv6_net_exit(struct net *net) | ||
2216 | { | ||
2217 | sk_release_kernel(net->ipv6.tcp_sk); | ||
2218 | } | ||
2219 | |||
2220 | static struct pernet_operations tcpv6_net_ops = { | ||
2221 | .init = tcpv6_net_init, | ||
2222 | .exit = tcpv6_net_exit, | ||
2223 | }; | ||
2224 | |||
2201 | int __init tcpv6_init(void) | 2225 | int __init tcpv6_init(void) |
2202 | { | 2226 | { |
2203 | int ret; | 2227 | int ret; |
@@ -2211,8 +2235,7 @@ int __init tcpv6_init(void) | |||
2211 | if (ret) | 2235 | if (ret) |
2212 | goto out_tcpv6_protocol; | 2236 | goto out_tcpv6_protocol; |
2213 | 2237 | ||
2214 | ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, | 2238 | ret = register_pernet_subsys(&tcpv6_net_ops); |
2215 | SOCK_RAW, IPPROTO_TCP); | ||
2216 | if (ret) | 2239 | if (ret) |
2217 | goto out_tcpv6_protosw; | 2240 | goto out_tcpv6_protosw; |
2218 | out: | 2241 | out: |
@@ -2227,7 +2250,7 @@ out_tcpv6_protosw: | |||
2227 | 2250 | ||
2228 | void tcpv6_exit(void) | 2251 | void tcpv6_exit(void) |
2229 | { | 2252 | { |
2230 | sock_release(tcp6_socket); | 2253 | unregister_pernet_subsys(&tcpv6_net_ops); |
2231 | inet6_unregister_protosw(&tcpv6_protosw); | 2254 | inet6_unregister_protosw(&tcpv6_protosw); |
2232 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2255 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2233 | } | 2256 | } |