aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c45
1 files changed, 35 insertions, 10 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b47cce8fea44..caf0cc1c00e1 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 */
73static struct socket *tcp6_socket;
74
75static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); 72static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
76static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); 73static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
77static void tcp_v6_send_check(struct sock *sk, int len, 74static void tcp_v6_send_check(struct sock *sk, int len,
@@ -991,6 +988,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
991 struct tcphdr *th = tcp_hdr(skb), *t1; 988 struct tcphdr *th = tcp_hdr(skb), *t1;
992 struct sk_buff *buff; 989 struct sk_buff *buff;
993 struct flowi fl; 990 struct flowi fl;
991 struct net *net = skb->dst->dev->nd_net;
992 struct sock *ctl_sk = net->ipv6.tcp_sk;
994 unsigned int tot_len = sizeof(*th); 993 unsigned int tot_len = sizeof(*th);
995#ifdef CONFIG_TCP_MD5SIG 994#ifdef CONFIG_TCP_MD5SIG
996 struct tcp_md5sig_key *key; 995 struct tcp_md5sig_key *key;
@@ -1075,10 +1074,10 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
1075 * Underlying function will use this to retrieve the network 1074 * Underlying function will use this to retrieve the network
1076 * namespace 1075 * namespace
1077 */ 1076 */
1078 if (!ip6_dst_lookup(tcp6_socket->sk, &buff->dst, &fl)) { 1077 if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
1079 1078
1080 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { 1079 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
1081 ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); 1080 ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
1082 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); 1081 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
1083 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); 1082 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
1084 return; 1083 return;
@@ -1094,6 +1093,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
1094 struct tcphdr *th = tcp_hdr(skb), *t1; 1093 struct tcphdr *th = tcp_hdr(skb), *t1;
1095 struct sk_buff *buff; 1094 struct sk_buff *buff;
1096 struct flowi fl; 1095 struct flowi fl;
1096 struct net *net = skb->dev->nd_net;
1097 struct sock *ctl_sk = net->ipv6.tcp_sk;
1097 unsigned int tot_len = sizeof(struct tcphdr); 1098 unsigned int tot_len = sizeof(struct tcphdr);
1098 __be32 *topt; 1099 __be32 *topt;
1099#ifdef CONFIG_TCP_MD5SIG 1100#ifdef CONFIG_TCP_MD5SIG
@@ -1175,9 +1176,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
1175 fl.fl_ip_sport = t1->source; 1176 fl.fl_ip_sport = t1->source;
1176 security_skb_classify_flow(skb, &fl); 1177 security_skb_classify_flow(skb, &fl);
1177 1178
1178 if (!ip6_dst_lookup(tcp6_socket->sk, &buff->dst, &fl)) { 1179 if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
1179 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { 1180 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
1180 ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); 1181 ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
1181 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); 1182 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
1182 return; 1183 return;
1183 } 1184 }
@@ -2198,6 +2199,31 @@ static struct inet_protosw tcpv6_protosw = {
2198 INET_PROTOSW_ICSK, 2199 INET_PROTOSW_ICSK,
2199}; 2200};
2200 2201
2202static int tcpv6_net_init(struct net *net)
2203{
2204 int err;
2205 struct socket *sock;
2206 struct sock *sk;
2207
2208 err = inet_csk_ctl_sock_create(&sock, PF_INET6, SOCK_RAW, IPPROTO_TCP);
2209 if (err)
2210 return err;
2211
2212 net->ipv6.tcp_sk = sk = sock->sk;
2213 sk_change_net(sk, net);
2214 return err;
2215}
2216
2217static void tcpv6_net_exit(struct net *net)
2218{
2219 sk_release_kernel(net->ipv6.tcp_sk);
2220}
2221
2222static struct pernet_operations tcpv6_net_ops = {
2223 .init = tcpv6_net_init,
2224 .exit = tcpv6_net_exit,
2225};
2226
2201int __init tcpv6_init(void) 2227int __init tcpv6_init(void)
2202{ 2228{
2203 int ret; 2229 int ret;
@@ -2211,8 +2237,7 @@ int __init tcpv6_init(void)
2211 if (ret) 2237 if (ret)
2212 goto out_tcpv6_protocol; 2238 goto out_tcpv6_protocol;
2213 2239
2214 ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, 2240 ret = register_pernet_subsys(&tcpv6_net_ops);
2215 SOCK_RAW, IPPROTO_TCP);
2216 if (ret) 2241 if (ret)
2217 goto out_tcpv6_protosw; 2242 goto out_tcpv6_protosw;
2218out: 2243out:
@@ -2227,7 +2252,7 @@ out_tcpv6_protosw:
2227 2252
2228void tcpv6_exit(void) 2253void tcpv6_exit(void)
2229{ 2254{
2230 sock_release(tcp6_socket); 2255 unregister_pernet_subsys(&tcpv6_net_ops);
2231 inet6_unregister_protosw(&tcpv6_protosw); 2256 inet6_unregister_protosw(&tcpv6_protosw);
2232 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); 2257 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
2233} 2258}