Commit 5a00d2d2 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji Committed by David S. Miller

[IPV6]: Convert /proc/net/tcp6 to seq_file.

parent a9b7fa76
...@@ -77,7 +77,8 @@ MODULE_LICENSE("GPL"); ...@@ -77,7 +77,8 @@ MODULE_LICENSE("GPL");
extern int raw6_proc_init(void); extern int raw6_proc_init(void);
extern int raw6_proc_exit(void); extern int raw6_proc_exit(void);
extern int tcp6_get_info(char *, char **, off_t, int); extern int tcp6_proc_init(void);
extern void tcp6_proc_exit(void);
extern int udp6_proc_init(void); extern int udp6_proc_init(void);
extern void udp6_proc_exit(void); extern void udp6_proc_exit(void);
...@@ -789,7 +790,7 @@ static int __init inet6_init(void) ...@@ -789,7 +790,7 @@ static int __init inet6_init(void)
err = -ENOMEM; err = -ENOMEM;
if (raw6_proc_init()) if (raw6_proc_init())
goto proc_raw6_fail; goto proc_raw6_fail;
if (!proc_net_create("tcp6", 0, tcp6_get_info)) if (tcp6_proc_init())
goto proc_tcp6_fail; goto proc_tcp6_fail;
if (udp6_proc_init()) if (udp6_proc_init())
goto proc_udp6_fail; goto proc_udp6_fail;
...@@ -824,7 +825,7 @@ static int __init inet6_init(void) ...@@ -824,7 +825,7 @@ static int __init inet6_init(void)
proc_misc6_fail: proc_misc6_fail:
udp6_proc_exit(); udp6_proc_exit();
proc_udp6_fail: proc_udp6_fail:
proc_net_remove("tcp6"); tcp6_proc_exit();
proc_tcp6_fail: proc_tcp6_fail:
raw6_proc_exit(); raw6_proc_exit();
proc_raw6_fail: proc_raw6_fail:
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
* Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind * Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
* a single port at the same time. * a single port at the same time.
* YOSHIFUJI Hideaki @USAGI: convert /proc/net/tcp6 to seq_file.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -55,6 +56,9 @@ ...@@ -55,6 +56,9 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static void tcp_v6_send_reset(struct sk_buff *skb); static void tcp_v6_send_reset(struct sk_buff *skb);
static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req); static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req);
static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
...@@ -1934,7 +1938,8 @@ static int tcp_v6_destroy_sock(struct sock *sk) ...@@ -1934,7 +1938,8 @@ static int tcp_v6_destroy_sock(struct sock *sk)
} }
/* Proc filesystem TCPv6 sock list dumping. */ /* Proc filesystem TCPv6 sock list dumping. */
static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf, int i, int uid) static void get_openreq6(struct seq_file *seq,
struct sock *sk, struct open_request *req, int i, int uid)
{ {
struct in6_addr *dest, *src; struct in6_addr *dest, *src;
int ttd = req->expires - jiffies; int ttd = req->expires - jiffies;
...@@ -1944,9 +1949,9 @@ static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf ...@@ -1944,9 +1949,9 @@ static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf
src = &req->af.v6_req.loc_addr; src = &req->af.v6_req.loc_addr;
dest = &req->af.v6_req.rmt_addr; dest = &req->af.v6_req.rmt_addr;
sprintf(tmpbuf, seq_printf(seq,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p", "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p\n",
i, i,
src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[0], src->s6_addr32[1],
src->s6_addr32[2], src->s6_addr32[3], src->s6_addr32[2], src->s6_addr32[3],
...@@ -1965,7 +1970,7 @@ static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf ...@@ -1965,7 +1970,7 @@ static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf
0, req); 0, req);
} }
static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i) static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
{ {
struct in6_addr *dest, *src; struct in6_addr *dest, *src;
__u16 destp, srcp; __u16 destp, srcp;
...@@ -1993,9 +1998,9 @@ static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i) ...@@ -1993,9 +1998,9 @@ static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
timer_expires = jiffies; timer_expires = jiffies;
} }
sprintf(tmpbuf, seq_printf(seq,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d", "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n",
i, i,
src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[0], src->s6_addr32[1],
src->s6_addr32[2], src->s6_addr32[3], srcp, src->s6_addr32[2], src->s6_addr32[3], srcp,
...@@ -2014,7 +2019,8 @@ static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i) ...@@ -2014,7 +2019,8 @@ static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
); );
} }
static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) static void get_timewait6_sock(struct seq_file *seq,
struct tcp_tw_bucket *tw, int i)
{ {
struct in6_addr *dest, *src; struct in6_addr *dest, *src;
__u16 destp, srcp; __u16 destp, srcp;
...@@ -2028,9 +2034,9 @@ static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) ...@@ -2028,9 +2034,9 @@ static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
destp = ntohs(tw->dport); destp = ntohs(tw->dport);
srcp = ntohs(tw->sport); srcp = ntohs(tw->sport);
sprintf(tmpbuf, seq_printf(seq,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p", "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p\n",
i, i,
src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[0], src->s6_addr32[1],
src->s6_addr32[2], src->s6_addr32[3], srcp, src->s6_addr32[2], src->s6_addr32[3], srcp,
...@@ -2041,131 +2047,54 @@ static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i) ...@@ -2041,131 +2047,54 @@ static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
atomic_read(&tw->refcnt), tw); atomic_read(&tw->refcnt), tw);
} }
#define LINE_LEN 190 static int tcp6_seq_show(struct seq_file *seq, void *v)
#define LINE_FMT "%-190s\n"
int tcp6_get_info(char *buffer, char **start, off_t offset, int length)
{ {
int len = 0, num = 0, i; struct tcp_iter_state *st;
off_t begin, pos = 0;
char tmpbuf[LINE_LEN+2]; if (v == (void *)1) {
seq_printf(seq,
if (offset < LINE_LEN+1) " sl "
len += sprintf(buffer, LINE_FMT, "local_address "
" sl " /* 6 */ "remote_address "
"local_address " /* 38 */ "st tx_queue rx_queue tr tm->when retrnsmt"
"remote_address " /* 38 */ " uid timeout inode\n");
"st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */ goto out;
" uid timeout inode"); /* 21 */
/*----*/
/*144 */
pos = LINE_LEN+1;
/* First, walk listening socket table. */
tcp_listen_lock();
for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
struct sock *sk = tcp_listening_hash[i];
struct tcp_listen_opt *lopt;
int k;
for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
struct open_request *req;
int uid;
struct tcp_opt *tp = tcp_sk(sk);
if (sk->family != PF_INET6)
continue;
pos += LINE_LEN+1;
if (pos >= offset) {
get_tcp6_sock(sk, tmpbuf, num);
len += sprintf(buffer+len, LINE_FMT, tmpbuf);
if (pos >= offset + length) {
tcp_listen_unlock();
goto out_no_bh;
}
}
uid = sock_i_uid(sk);
read_lock_bh(&tp->syn_wait_lock);
lopt = tp->listen_opt;
if (lopt && lopt->qlen != 0) {
for (k=0; k<TCP_SYNQ_HSIZE; k++) {
for (req = lopt->syn_table[k]; req; req = req->dl_next, num++) {
if (req->class->family != PF_INET6)
continue;
pos += LINE_LEN+1;
if (pos <= offset)
continue;
get_openreq6(sk, req, tmpbuf, num, uid);
len += sprintf(buffer+len, LINE_FMT, tmpbuf);
if (pos >= offset + length) {
read_unlock_bh(&tp->syn_wait_lock);
tcp_listen_unlock();
goto out_no_bh;
}
}
}
} }
read_unlock_bh(&tp->syn_wait_lock); st = seq->private;
/* Completed requests are in normal socket hash table */ switch (st->state) {
} case TCP_SEQ_STATE_LISTENING:
case TCP_SEQ_STATE_ESTABLISHED:
get_tcp6_sock(seq, v, st->num);
break;
case TCP_SEQ_STATE_OPENREQ:
get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
break;
case TCP_SEQ_STATE_TIME_WAIT:
get_timewait6_sock(seq, v, st->num);
break;
} }
tcp_listen_unlock(); out:
return 0;
local_bh_disable(); }
/* Next, walk established hash chain. */ static struct file_operations tcp6_seq_fops;
for (i = 0; i < tcp_ehash_size; i++) { static struct tcp_seq_afinfo tcp6_seq_afinfo = {
struct tcp_ehash_bucket *head = &tcp_ehash[i]; .owner = THIS_MODULE,
struct sock *sk; .name = "tcp6",
struct tcp_tw_bucket *tw; .family = AF_INET6,
.seq_show = tcp6_seq_show,
.seq_fops = &tcp6_seq_fops,
};
read_lock(&head->lock); int __init tcp6_proc_init(void)
for(sk = head->chain; sk; sk = sk->next, num++) { {
if (sk->family != PF_INET6) return tcp_proc_register(&tcp6_seq_afinfo);
continue; }
pos += LINE_LEN+1;
if (pos <= offset)
continue;
get_tcp6_sock(sk, tmpbuf, num);
len += sprintf(buffer+len, LINE_FMT, tmpbuf);
if (pos >= offset + length) {
read_unlock(&head->lock);
goto out;
}
}
for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain;
tw != NULL;
tw = (struct tcp_tw_bucket *)tw->next, num++) {
if (tw->family != PF_INET6)
continue;
pos += LINE_LEN+1;
if (pos <= offset)
continue;
get_timewait6_sock(tw, tmpbuf, num);
len += sprintf(buffer+len, LINE_FMT, tmpbuf);
if (pos >= offset + length) {
read_unlock(&head->lock);
goto out;
}
}
read_unlock(&head->lock);
}
out: void tcp6_proc_exit(void)
local_bh_enable(); {
out_no_bh: tcp_proc_unregister(&tcp6_seq_afinfo);
begin = len - (pos - offset);
*start = buffer + begin;
len -= begin;
if (len > length)
len = length;
if (len < 0)
len = 0;
return len;
} }
struct proto tcpv6_prot = { struct proto tcpv6_prot = {
......
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