[NETNS][IPV4] tcp - make proc handle the network namespaces
authorDaniel Lezcano <dlezcano@fr.ibm.com>
Fri, 21 Mar 2008 11:13:54 +0000 (04:13 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 21 Mar 2008 11:13:54 +0000 (04:13 -0700)
This patch, like udp proc, makes the proc functions to take care of
which namespace the socket belongs.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/tcp.h
net/ipv4/tcp_ipv4.c

index 11119e33acfe16af8e735f071d924388c22c40d5..6b08dab1b1fab6446ec9417d83aef30425934a68 100644 (file)
@@ -1328,6 +1328,7 @@ struct tcp_seq_afinfo {
 };
 
 struct tcp_iter_state {
+       struct net              *net;
        sa_family_t             family;
        enum tcp_seq_states     state;
        struct sock             *syn_wait_sk;
index a79e324638eb3c89ec222d58b7d375da82c5ae02..f9b30dc3bd6cedf422467ff46520c582c328feba 100644 (file)
@@ -1948,6 +1948,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
        struct hlist_node *node;
        struct sock *sk = cur;
        struct tcp_iter_state* st = seq->private;
+       struct net *net = st->net;
 
        if (!sk) {
                st->bucket = 0;
@@ -1964,7 +1965,8 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
                req = req->dl_next;
                while (1) {
                        while (req) {
-                               if (req->rsk_ops->family == st->family) {
+                               if (req->rsk_ops->family == st->family &&
+                                   req->sk->sk_net == net) {
                                        cur = req;
                                        goto out;
                                }
@@ -1988,7 +1990,7 @@ get_req:
        }
 get_sk:
        sk_for_each_from(sk, node) {
-               if (sk->sk_family == st->family) {
+               if (sk->sk_family == st->family && sk->sk_net == net) {
                        cur = sk;
                        goto out;
                }
@@ -2027,6 +2029,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
 static void *established_get_first(struct seq_file *seq)
 {
        struct tcp_iter_state* st = seq->private;
+       struct net *net = st->net;
        void *rc = NULL;
 
        for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
@@ -2037,7 +2040,8 @@ static void *established_get_first(struct seq_file *seq)
 
                read_lock_bh(lock);
                sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
-                       if (sk->sk_family != st->family) {
+                       if (sk->sk_family != st->family ||
+                           sk->sk_net != net) {
                                continue;
                        }
                        rc = sk;
@@ -2046,7 +2050,8 @@ static void *established_get_first(struct seq_file *seq)
                st->state = TCP_SEQ_STATE_TIME_WAIT;
                inet_twsk_for_each(tw, node,
                                   &tcp_hashinfo.ehash[st->bucket].twchain) {
-                       if (tw->tw_family != st->family) {
+                       if (tw->tw_family != st->family &&
+                           tw->tw_net != net) {
                                continue;
                        }
                        rc = tw;
@@ -2065,6 +2070,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
        struct inet_timewait_sock *tw;
        struct hlist_node *node;
        struct tcp_iter_state* st = seq->private;
+       struct net *net = st->net;
 
        ++st->num;
 
@@ -2072,7 +2078,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
                tw = cur;
                tw = tw_next(tw);
 get_tw:
-               while (tw && tw->tw_family != st->family) {
+               while (tw && tw->tw_family != st->family && tw->tw_net != net) {
                        tw = tw_next(tw);
                }
                if (tw) {
@@ -2093,7 +2099,7 @@ get_tw:
                sk = sk_next(sk);
 
        sk_for_each_from(sk, node) {
-               if (sk->sk_family == st->family)
+               if (sk->sk_family == st->family && sk->sk_net == net)
                        goto found;
        }
 
@@ -2201,6 +2207,7 @@ static int tcp_seq_open(struct inode *inode, struct file *file)
        struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
        struct seq_file *seq;
        struct tcp_iter_state *s;
+       struct net *net;
        int rc;
 
        if (unlikely(afinfo == NULL))
@@ -2209,24 +2216,43 @@ static int tcp_seq_open(struct inode *inode, struct file *file)
        s = kzalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
                return -ENOMEM;
+
+       rc = -ENXIO;
+       net = get_proc_net(inode);
+       if (!net)
+               goto out_kfree;
+
        s->family               = afinfo->family;
        s->seq_ops.start        = tcp_seq_start;
        s->seq_ops.next         = tcp_seq_next;
        s->seq_ops.show         = afinfo->seq_show;
        s->seq_ops.stop         = tcp_seq_stop;
+       s->net                  = net;
 
        rc = seq_open(file, &s->seq_ops);
        if (rc)
-               goto out_kfree;
-       seq          = file->private_data;
+               goto out_put_net;
+       seq = file->private_data;
        seq->private = s;
 out:
        return rc;
+out_put_net:
+       put_net(net);
 out_kfree:
        kfree(s);
        goto out;
 }
 
+static int tcp_seq_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq = file->private_data;
+       struct tcp_iter_state *s = seq->private;
+
+       put_net(s->net);
+       seq_release_private(inode, file);
+       return 0;
+}
+
 int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
 {
        int rc = 0;
@@ -2238,7 +2264,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
        afinfo->seq_fops->open          = tcp_seq_open;
        afinfo->seq_fops->read          = seq_read;
        afinfo->seq_fops->llseek        = seq_lseek;
-       afinfo->seq_fops->release       = seq_release_private;
+       afinfo->seq_fops->release       = tcp_seq_release;
 
        p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
        if (p)