Commit f40c8174 authored by Daniel Lezcano's avatar Daniel Lezcano Committed by David S. Miller

[NETNS][IPV4] tcp - make proc handle the network namespaces

This patch, like udp proc, makes the proc functions to take care of
which namespace the socket belongs.
Signed-off-by: default avatarDaniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8d9f1744
...@@ -1328,6 +1328,7 @@ struct tcp_seq_afinfo { ...@@ -1328,6 +1328,7 @@ struct tcp_seq_afinfo {
}; };
struct tcp_iter_state { struct tcp_iter_state {
struct net *net;
sa_family_t family; sa_family_t family;
enum tcp_seq_states state; enum tcp_seq_states state;
struct sock *syn_wait_sk; struct sock *syn_wait_sk;
......
...@@ -1948,6 +1948,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -1948,6 +1948,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
struct hlist_node *node; struct hlist_node *node;
struct sock *sk = cur; struct sock *sk = cur;
struct tcp_iter_state* st = seq->private; struct tcp_iter_state* st = seq->private;
struct net *net = st->net;
if (!sk) { if (!sk) {
st->bucket = 0; st->bucket = 0;
...@@ -1964,7 +1965,8 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -1964,7 +1965,8 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
req = req->dl_next; req = req->dl_next;
while (1) { while (1) {
while (req) { while (req) {
if (req->rsk_ops->family == st->family) { if (req->rsk_ops->family == st->family &&
req->sk->sk_net == net) {
cur = req; cur = req;
goto out; goto out;
} }
...@@ -1988,7 +1990,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -1988,7 +1990,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
} }
get_sk: get_sk:
sk_for_each_from(sk, node) { sk_for_each_from(sk, node) {
if (sk->sk_family == st->family) { if (sk->sk_family == st->family && sk->sk_net == net) {
cur = sk; cur = sk;
goto out; goto out;
} }
...@@ -2027,6 +2029,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos) ...@@ -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) static void *established_get_first(struct seq_file *seq)
{ {
struct tcp_iter_state* st = seq->private; struct tcp_iter_state* st = seq->private;
struct net *net = st->net;
void *rc = NULL; void *rc = NULL;
for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) { 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) ...@@ -2037,7 +2040,8 @@ static void *established_get_first(struct seq_file *seq)
read_lock_bh(lock); read_lock_bh(lock);
sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { 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; continue;
} }
rc = sk; rc = sk;
...@@ -2046,7 +2050,8 @@ static void *established_get_first(struct seq_file *seq) ...@@ -2046,7 +2050,8 @@ static void *established_get_first(struct seq_file *seq)
st->state = TCP_SEQ_STATE_TIME_WAIT; st->state = TCP_SEQ_STATE_TIME_WAIT;
inet_twsk_for_each(tw, node, inet_twsk_for_each(tw, node,
&tcp_hashinfo.ehash[st->bucket].twchain) { &tcp_hashinfo.ehash[st->bucket].twchain) {
if (tw->tw_family != st->family) { if (tw->tw_family != st->family &&
tw->tw_net != net) {
continue; continue;
} }
rc = tw; rc = tw;
...@@ -2065,6 +2070,7 @@ static void *established_get_next(struct seq_file *seq, void *cur) ...@@ -2065,6 +2070,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
struct inet_timewait_sock *tw; struct inet_timewait_sock *tw;
struct hlist_node *node; struct hlist_node *node;
struct tcp_iter_state* st = seq->private; struct tcp_iter_state* st = seq->private;
struct net *net = st->net;
++st->num; ++st->num;
...@@ -2072,7 +2078,7 @@ static void *established_get_next(struct seq_file *seq, void *cur) ...@@ -2072,7 +2078,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
tw = cur; tw = cur;
tw = tw_next(tw); tw = tw_next(tw);
get_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); tw = tw_next(tw);
} }
if (tw) { if (tw) {
...@@ -2093,7 +2099,7 @@ static void *established_get_next(struct seq_file *seq, void *cur) ...@@ -2093,7 +2099,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
sk = sk_next(sk); sk = sk_next(sk);
sk_for_each_from(sk, node) { sk_for_each_from(sk, node) {
if (sk->sk_family == st->family) if (sk->sk_family == st->family && sk->sk_net == net)
goto found; goto found;
} }
...@@ -2201,6 +2207,7 @@ static int tcp_seq_open(struct inode *inode, struct file *file) ...@@ -2201,6 +2207,7 @@ static int tcp_seq_open(struct inode *inode, struct file *file)
struct tcp_seq_afinfo *afinfo = PDE(inode)->data; struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
struct seq_file *seq; struct seq_file *seq;
struct tcp_iter_state *s; struct tcp_iter_state *s;
struct net *net;
int rc; int rc;
if (unlikely(afinfo == NULL)) if (unlikely(afinfo == NULL))
...@@ -2209,24 +2216,43 @@ static int tcp_seq_open(struct inode *inode, struct file *file) ...@@ -2209,24 +2216,43 @@ static int tcp_seq_open(struct inode *inode, struct file *file)
s = kzalloc(sizeof(*s), GFP_KERNEL); s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s) if (!s)
return -ENOMEM; return -ENOMEM;
rc = -ENXIO;
net = get_proc_net(inode);
if (!net)
goto out_kfree;
s->family = afinfo->family; s->family = afinfo->family;
s->seq_ops.start = tcp_seq_start; s->seq_ops.start = tcp_seq_start;
s->seq_ops.next = tcp_seq_next; s->seq_ops.next = tcp_seq_next;
s->seq_ops.show = afinfo->seq_show; s->seq_ops.show = afinfo->seq_show;
s->seq_ops.stop = tcp_seq_stop; s->seq_ops.stop = tcp_seq_stop;
s->net = net;
rc = seq_open(file, &s->seq_ops); rc = seq_open(file, &s->seq_ops);
if (rc) if (rc)
goto out_kfree; goto out_put_net;
seq = file->private_data; seq = file->private_data;
seq->private = s; seq->private = s;
out: out:
return rc; return rc;
out_put_net:
put_net(net);
out_kfree: out_kfree:
kfree(s); kfree(s);
goto out; 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 tcp_proc_register(struct tcp_seq_afinfo *afinfo)
{ {
int rc = 0; int rc = 0;
...@@ -2238,7 +2264,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo) ...@@ -2238,7 +2264,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
afinfo->seq_fops->open = tcp_seq_open; afinfo->seq_fops->open = tcp_seq_open;
afinfo->seq_fops->read = seq_read; afinfo->seq_fops->read = seq_read;
afinfo->seq_fops->llseek = seq_lseek; 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); p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
if (p) if (p)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment