[NETNS][IPV6] tcp6 - make proc per namespace
[safe/jmp/linux-2.6] / net / ipv6 / tcp_ipv6.c
index aacbb76..56d0cea 100644 (file)
@@ -69,9 +69,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,
@@ -753,7 +750,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
 
        hp = tcp_get_md5sig_pool();
        if (!hp) {
-               printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__);
+               printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
                goto clear_hash_noput;
        }
        bp = &hp->md5_blk.ip6;
@@ -793,17 +790,17 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
        /* Now store the hash into the packet */
        err = crypto_hash_init(desc);
        if (err) {
-               printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__);
+               printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
                goto clear_hash;
        }
        err = crypto_hash_update(desc, sg, nbytes);
        if (err) {
-               printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__);
+               printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
                goto clear_hash;
        }
        err = crypto_hash_final(desc, md5_hash);
        if (err) {
-               printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__);
+               printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
                goto clear_hash;
        }
 
@@ -991,6 +988,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 = skb->dst->dev->nd_net;
+       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 +1074,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 +1093,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 = skb->dev->nd_net;
+       struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(struct tcphdr);
        __be32 *topt;
 #ifdef CONFIG_TCP_MD5SIG
@@ -1175,9 +1176,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;
                }
@@ -2128,14 +2129,14 @@ 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
 
@@ -2198,6 +2199,31 @@ static struct inet_protosw tcpv6_protosw = {
                                INET_PROTOSW_ICSK,
 };
 
+static int tcpv6_net_init(struct net *net)
+{
+       int err;
+       struct socket *sock;
+       struct sock *sk;
+
+       err = inet_csk_ctl_sock_create(&sock, PF_INET6, SOCK_RAW, IPPROTO_TCP);
+       if (err)
+               return err;
+
+       net->ipv6.tcp_sk = sk = sock->sk;
+       sk_change_net(sk, net);
+       return err;
+}
+
+static void tcpv6_net_exit(struct net *net)
+{
+       sk_release_kernel(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 +2237,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 +2252,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);
 }