diff options
| -rw-r--r-- | include/net/tcp.h | 28 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 8 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 159 | ||||
| -rw-r--r-- | net/netsyms.c | 2 |
4 files changed, 119 insertions, 78 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 080e2f0d06f0..158ee68198b4 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -35,6 +35,7 @@ #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include <linux/ipv6.h> #endif +#include <linux/seq_file.h> /* This is for all connections with a full identity, no wildcards. * New scheme, half the table is for TIME_WAIT, the other half is @@ -1889,4 +1890,31 @@ static inline void tcp_mib_init(void) TCP_ADD_STATS_USER(TcpMaxConn, -1); } +/* /proc */ +enum tcp_seq_states { + TCP_SEQ_STATE_LISTENING, + TCP_SEQ_STATE_OPENREQ, + TCP_SEQ_STATE_ESTABLISHED, + TCP_SEQ_STATE_TIME_WAIT, +}; + +struct tcp_seq_afinfo { + struct module *owner; + char *name; + sa_family_t family; + int (*seq_show) (struct seq_file *m, void *v); + struct file_operations *seq_fops; +}; + +struct tcp_iter_state { + sa_family_t family; + enum tcp_seq_states state; + struct sock *syn_wait_sk; + int bucket, sbucket, num, uid; + struct seq_operations seq_ops; +}; + +extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo); +extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo); + #endif /* _TCP_H */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f08e534ea02f..f96acad1857c 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1237,8 +1237,8 @@ extern void fib_proc_exit(void); extern int ip_misc_proc_init(void); extern int raw_proc_init(void); extern void raw_proc_exit(void); -extern int tcp_proc_init(void); -extern void tcp_proc_exit(void); +extern int tcp4_proc_init(void); +extern void tcp4_proc_exit(void); extern int udp4_proc_init(void); extern void udp4_proc_exit(void); @@ -1248,7 +1248,7 @@ int __init ipv4_proc_init(void) if (raw_proc_init()) goto out_raw; - if (tcp_proc_init()) + if (tcp4_proc_init()) goto out_tcp; if (udp4_proc_init()) goto out_udp; @@ -1263,7 +1263,7 @@ out_misc: out_fib: udp4_proc_exit(); out_udp: - tcp_proc_exit(); + tcp4_proc_exit(); out_tcp: raw_proc_exit(); out_raw: diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2ad587593075..544a181ff550 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2129,19 +2129,6 @@ static int tcp_v4_destroy_sock(struct sock *sk) #ifdef CONFIG_PROC_FS /* Proc filesystem TCP sock list dumping. */ -enum tcp_seq_states { - TCP_SEQ_STATE_LISTENING, - TCP_SEQ_STATE_OPENREQ, - TCP_SEQ_STATE_ESTABLISHED, - TCP_SEQ_STATE_TIME_WAIT, -}; - -struct tcp_iter_state { - enum tcp_seq_states state; - struct sock *syn_wait_sk; - int bucket, sbucket, num, uid; -}; - static void *listening_get_first(struct seq_file *seq) { struct tcp_iter_state* st = seq->private; @@ -2155,7 +2142,7 @@ static void *listening_get_first(struct seq_file *seq) if (!sk) continue; ++st->num; - if (TCP_INET_FAMILY(sk->family)) { + if (sk->family == st->family) { rc = sk; goto out; } @@ -2169,7 +2156,7 @@ static void *listening_get_first(struct seq_file *seq) ++st->sbucket) { for (req = tp->listen_opt->syn_table[st->sbucket]; req; req = req->dl_next, ++st->num) { - if (!TCP_INET_FAMILY(req->class->family)) + if (req->class->family != st->family) continue; rc = req; goto out; @@ -2197,7 +2184,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) while (1) { while (req) { ++st->num; - if (TCP_INET_FAMILY(req->class->family)) { + if (req->class->family == st->family) { cur = req; goto out; } @@ -2215,7 +2202,7 @@ get_req: sk = sk->next; get_sk: while (sk) { - if (TCP_INET_FAMILY(sk->family)) { + if (sk->family == st->family) { cur = sk; goto out; } @@ -2262,7 +2249,7 @@ static void *established_get_first(struct seq_file *seq) read_lock(&tcp_ehash[st->bucket].lock); for (sk = tcp_ehash[st->bucket].chain; sk; sk = sk->next, ++st->num) { - if (!TCP_INET_FAMILY(sk->family)) + if (sk->family != st->family) continue; rc = sk; goto out; @@ -2271,7 +2258,7 @@ static void *established_get_first(struct seq_file *seq) for (tw = (struct tcp_tw_bucket *) tcp_ehash[st->bucket + tcp_ehash_size].chain; tw; tw = (struct tcp_tw_bucket *)tw->next, ++st->num) { - if (!TCP_INET_FAMILY(tw->family)) + if (tw->family != st->family) continue; rc = tw; goto out; @@ -2293,7 +2280,7 @@ static void *established_get_next(struct seq_file *seq, void *cur) tw = cur; tw = (struct tcp_tw_bucket *)tw->next; get_tw: - while (tw && !TCP_INET_FAMILY(tw->family)) { + while (tw && tw->family != st->family) { ++st->num; tw = (struct tcp_tw_bucket *)tw->next; } @@ -2313,7 +2300,7 @@ get_tw: } else sk = sk->next; - while (sk && !TCP_INET_FAMILY(sk->family)) { + while (sk && sk->family != st->family) { ++st->num; sk = sk->next; } @@ -2417,8 +2404,66 @@ static void tcp_seq_stop(struct seq_file *seq, void *v) } } -static void get_openreq(struct sock *sk, struct open_request *req, - char *tmpbuf, int i, int uid) +static int tcp_seq_open(struct inode *inode, struct file *file) +{ + struct tcp_seq_afinfo *afinfo = PDE(inode)->data; + struct seq_file *seq; + int rc = -ENOMEM; + struct tcp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + + if (!s) + goto out; + memset(s, 0, sizeof(*s)); + 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; + + rc = seq_open(file, &s->seq_ops); + if (rc) + goto out_kfree; + seq = file->private_data; + seq->private = s; +out: + return rc; +out_kfree: + kfree(s); + goto out; +} + +int tcp_proc_register(struct tcp_seq_afinfo *afinfo) +{ + int rc = 0; + struct proc_dir_entry *p; + + if (!afinfo) + return -EINVAL; + afinfo->seq_fops->owner = afinfo->owner; + 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; + + p = create_proc_entry(afinfo->name, S_IRUGO, proc_net); + if (p) { + p->data = afinfo; + p->proc_fops = afinfo->seq_fops; + } else + rc = -ENOMEM; + return rc; +} + +void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo) +{ + if (!afinfo) + return; + remove_proc_entry(afinfo->name, proc_net); + memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); +} + +static void get_openreq4(struct sock *sk, struct open_request *req, + char *tmpbuf, int i, int uid) { int ttd = req->expires - jiffies; @@ -2441,7 +2486,7 @@ static void get_openreq(struct sock *sk, struct open_request *req, req); } -static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i) +static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) { int timer_active; unsigned long timer_expires; @@ -2481,7 +2526,7 @@ static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i) tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh); } -static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) +static void get_timewait4_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) { unsigned int dest, src; __u16 destp, srcp; @@ -2504,7 +2549,7 @@ static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) #define TMPSZ 150 -static int tcp_seq_show(struct seq_file *seq, void *v) +static int tcp4_seq_show(struct seq_file *seq, void *v) { struct tcp_iter_state* st; char tmpbuf[TMPSZ + 1]; @@ -2521,13 +2566,13 @@ static int tcp_seq_show(struct seq_file *seq, void *v) switch (st->state) { case TCP_SEQ_STATE_LISTENING: case TCP_SEQ_STATE_ESTABLISHED: - get_tcp_sock(v, tmpbuf, st->num); + get_tcp4_sock(v, tmpbuf, st->num); break; case TCP_SEQ_STATE_OPENREQ: - get_openreq(st->syn_wait_sk, v, tmpbuf, st->num, st->uid); + get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid); break; case TCP_SEQ_STATE_TIME_WAIT: - get_timewait_sock(v, tmpbuf, st->num); + get_timewait4_sock(v, tmpbuf, st->num); break; } seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf); @@ -2535,57 +2580,23 @@ out: return 0; } -static struct seq_operations tcp_seq_ops = { - .start = tcp_seq_start, - .next = tcp_seq_next, - .stop = tcp_seq_stop, - .show = tcp_seq_show, -}; - -static int tcp_seq_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - int rc = -ENOMEM; - struct tcp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); - - if (!s) - goto out; - rc = seq_open(file, &tcp_seq_ops); - if (rc) - goto out_kfree; - seq = file->private_data; - seq->private = s; - memset(s, 0, sizeof(*s)); -out: - return rc; -out_kfree: - kfree(s); - goto out; -} - -static struct file_operations tcp_seq_fops = { - .owner = THIS_MODULE, - .open = tcp_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, +static struct file_operations tcp4_seq_fops; +static struct tcp_seq_afinfo tcp4_seq_afinfo = { + .owner = THIS_MODULE, + .name = "tcp", + .family = AF_INET, + .seq_show = tcp4_seq_show, + .seq_fops = &tcp4_seq_fops, }; -int __init tcp_proc_init(void) +int __init tcp4_proc_init(void) { - int rc = 0; - struct proc_dir_entry *p = create_proc_entry("tcp", S_IRUGO, proc_net); - - if (p) - p->proc_fops = &tcp_seq_fops; - else - rc = -ENOMEM; - return rc; + return tcp_proc_register(&tcp4_seq_afinfo); } -void __init tcp_proc_exit(void) +void tcp4_proc_exit(void) { - remove_proc_entry("tcp", proc_net); + tcp_proc_unregister(&tcp4_seq_afinfo); } #endif /* CONFIG_PROC_FS */ diff --git a/net/netsyms.c b/net/netsyms.c index 8521972ee48e..c153585701e3 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -285,6 +285,8 @@ EXPORT_SYMBOL(unregister_inetaddr_notifier); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(udp_proc_register); EXPORT_SYMBOL(udp_proc_unregister); +EXPORT_SYMBOL(tcp_proc_register); +EXPORT_SYMBOL(tcp_proc_unregister); #endif /* needed for ip_gre -cw */ |
