[IPV6] ADDRCONF: Fix array size for sysctls.
[h-e-n] / net / ipv6 / tcp_ipv6.c
index b47cce8..378cc40 100644 (file)
@@ -60,6 +60,7 @@
 #include <net/dsfield.h>
 #include <net/timewait_sock.h>
 #include <net/netdma.h>
+#include <net/inet_common.h>
 
 #include <asm/uaccess.h>
 
@@ -69,9 +70,6 @@
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
 
-/* Socket used for sending RSTs and ACKs */
-static struct socket *tcp6_socket;
-
 static void    tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
 static void    tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
 static void    tcp_v6_send_check(struct sock *sk, int len,
@@ -324,7 +322,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct tcp_sock *tp;
        __u32 seq;
 
-       sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr,
+       sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr,
                        th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
 
        if (sk == NULL) {
@@ -991,6 +989,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
        struct tcphdr *th = tcp_hdr(skb), *t1;
        struct sk_buff *buff;
        struct flowi fl;
+       struct net *net = dev_net(skb->dst->dev);
+       struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(*th);
 #ifdef CONFIG_TCP_MD5SIG
        struct tcp_md5sig_key *key;
@@ -1075,10 +1075,10 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
         * Underlying function will use this to retrieve the network
         * namespace
         */
-       if (!ip6_dst_lookup(tcp6_socket->sk, &buff->dst, &fl)) {
+       if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
 
                if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
-                       ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
+                       ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
                        TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
                        TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
                        return;
@@ -1094,6 +1094,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
        struct tcphdr *th = tcp_hdr(skb), *t1;
        struct sk_buff *buff;
        struct flowi fl;
+       struct net *net = dev_net(skb->dev);
+       struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(struct tcphdr);
        __be32 *topt;
 #ifdef CONFIG_TCP_MD5SIG
@@ -1175,9 +1177,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
        fl.fl_ip_sport = t1->source;
        security_skb_classify_flow(skb, &fl);
 
-       if (!ip6_dst_lookup(tcp6_socket->sk, &buff->dst, &fl)) {
+       if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
                if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
-                       ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
+                       ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
                        TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
                        return;
                }
@@ -1217,7 +1219,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
        if (req)
                return tcp_check_req(sk, skb, req, prev);
 
-       nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo,
+       nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
                        &ipv6_hdr(skb)->saddr, th->source,
                        &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb));
 
@@ -1738,7 +1740,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
        TCP_SKB_CB(skb)->sacked = 0;
 
-       sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo,
+       sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo,
                        &ipv6_hdr(skb)->saddr, th->source,
                        &ipv6_hdr(skb)->daddr, ntohs(th->dest),
                        inet6_iif(skb));
@@ -1821,7 +1823,7 @@ do_time_wait:
        {
                struct sock *sk2;
 
-               sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo,
+               sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
                                            &ipv6_hdr(skb)->daddr,
                                            ntohs(th->dest), inet6_iif(skb));
                if (sk2 != NULL) {
@@ -2128,19 +2130,17 @@ static struct tcp_seq_afinfo tcp6_seq_afinfo = {
        .seq_fops       = &tcp6_seq_fops,
 };
 
-int __init tcp6_proc_init(void)
+int tcp6_proc_init(struct net *net)
 {
-       return tcp_proc_register(&tcp6_seq_afinfo);
+       return tcp_proc_register(net, &tcp6_seq_afinfo);
 }
 
-void tcp6_proc_exit(void)
+void tcp6_proc_exit(struct net *net)
 {
-       tcp_proc_unregister(&tcp6_seq_afinfo);
+       tcp_proc_unregister(net, &tcp6_seq_afinfo);
 }
 #endif
 
-DEFINE_PROTO_INUSE(tcpv6)
-
 struct proto tcpv6_prot = {
        .name                   = "TCPv6",
        .owner                  = THIS_MODULE,
@@ -2171,12 +2171,11 @@ struct proto tcpv6_prot = {
        .obj_size               = sizeof(struct tcp6_sock),
        .twsk_prot              = &tcp6_timewait_sock_ops,
        .rsk_prot               = &tcp6_request_sock_ops,
-       .hashinfo               = &tcp_hashinfo,
+       .h.hashinfo             = &tcp_hashinfo,
 #ifdef CONFIG_COMPAT
        .compat_setsockopt      = compat_tcp_setsockopt,
        .compat_getsockopt      = compat_tcp_getsockopt,
 #endif
-       REF_PROTO_INUSE(tcpv6)
 };
 
 static struct inet6_protocol tcpv6_protocol = {
@@ -2198,6 +2197,22 @@ static struct inet_protosw tcpv6_protosw = {
                                INET_PROTOSW_ICSK,
 };
 
+static int tcpv6_net_init(struct net *net)
+{
+       return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
+                                   SOCK_RAW, IPPROTO_TCP, net);
+}
+
+static void tcpv6_net_exit(struct net *net)
+{
+       inet_ctl_sock_destroy(net->ipv6.tcp_sk);
+}
+
+static struct pernet_operations tcpv6_net_ops = {
+       .init = tcpv6_net_init,
+       .exit = tcpv6_net_exit,
+};
+
 int __init tcpv6_init(void)
 {
        int ret;
@@ -2211,8 +2226,7 @@ int __init tcpv6_init(void)
        if (ret)
                goto out_tcpv6_protocol;
 
-       ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6,
-                                      SOCK_RAW, IPPROTO_TCP);
+       ret = register_pernet_subsys(&tcpv6_net_ops);
        if (ret)
                goto out_tcpv6_protosw;
 out:
@@ -2227,7 +2241,7 @@ out_tcpv6_protosw:
 
 void tcpv6_exit(void)
 {
-       sock_release(tcp6_socket);
+       unregister_pernet_subsys(&tcpv6_net_ops);
        inet6_unregister_protosw(&tcpv6_protosw);
        inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 }