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

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

parent b9d92bc3
...@@ -74,8 +74,10 @@ MODULE_LICENSE("GPL"); ...@@ -74,8 +74,10 @@ MODULE_LICENSE("GPL");
/* IPv6 procfs goodies... */ /* IPv6 procfs goodies... */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
extern int raw6_proc_init(void);
extern int raw6_proc_exit(void);
extern int anycast6_get_info(char *, char **, off_t, int); extern int anycast6_get_info(char *, char **, off_t, int);
extern int raw6_get_info(char *, char **, off_t, int);
extern int tcp6_get_info(char *, char **, off_t, int); extern int tcp6_get_info(char *, char **, off_t, int);
extern int udp6_get_info(char *, char **, off_t, int); extern int udp6_get_info(char *, char **, off_t, int);
extern int afinet6_get_info(char *, char **, off_t, int); extern int afinet6_get_info(char *, char **, off_t, int);
...@@ -786,7 +788,7 @@ static int __init inet6_init(void) ...@@ -786,7 +788,7 @@ static int __init inet6_init(void)
/* Create /proc/foo6 entries. */ /* Create /proc/foo6 entries. */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
err = -ENOMEM; err = -ENOMEM;
if (!proc_net_create("raw6", 0, raw6_get_info)) if (raw6_proc_init())
goto proc_raw6_fail; goto proc_raw6_fail;
if (!proc_net_create("tcp6", 0, tcp6_get_info)) if (!proc_net_create("tcp6", 0, tcp6_get_info))
goto proc_tcp6_fail; goto proc_tcp6_fail;
...@@ -827,7 +829,7 @@ static int __init inet6_init(void) ...@@ -827,7 +829,7 @@ static int __init inet6_init(void)
proc_udp6_fail: proc_udp6_fail:
proc_net_remove("tcp6"); proc_net_remove("tcp6");
proc_tcp6_fail: proc_tcp6_fail:
proc_net_remove("raw6"); raw6_proc_exit();
proc_raw6_fail: proc_raw6_fail:
igmp6_cleanup(); igmp6_cleanup();
#endif #endif
...@@ -852,7 +854,7 @@ static void inet6_exit(void) ...@@ -852,7 +854,7 @@ static void inet6_exit(void)
/* First of all disallow new sockets creation. */ /* First of all disallow new sockets creation. */
sock_unregister(PF_INET6); sock_unregister(PF_INET6);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_net_remove("raw6"); raw6_proc_exit();
proc_net_remove("tcp6"); proc_net_remove("tcp6");
proc_net_remove("udp6"); proc_net_remove("udp6");
proc_net_remove("sockstat6"); proc_net_remove("sockstat6");
......
...@@ -47,6 +47,9 @@ ...@@ -47,6 +47,9 @@
#include <net/rawv6.h> #include <net/rawv6.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE]; struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE];
rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED; rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED;
...@@ -831,10 +834,96 @@ static int rawv6_init_sk(struct sock *sk) ...@@ -831,10 +834,96 @@ static int rawv6_init_sk(struct sock *sk)
return(0); return(0);
} }
#define LINE_LEN 190 struct proto rawv6_prot = {
#define LINE_FMT "%-190s\n" .name = "RAW",
.close = rawv6_close,
.connect = udpv6_connect,
.disconnect = udp_disconnect,
.ioctl = rawv6_ioctl,
.init = rawv6_init_sk,
.destroy = inet6_destroy_sock,
.setsockopt = rawv6_setsockopt,
.getsockopt = rawv6_getsockopt,
.sendmsg = rawv6_sendmsg,
.recvmsg = rawv6_recvmsg,
.bind = rawv6_bind,
.backlog_rcv = rawv6_rcv_skb,
.hash = raw_v6_hash,
.unhash = raw_v6_unhash,
};
#ifdef CONFIG_PROC_FS
struct raw6_iter_state {
int bucket;
};
#define raw6_seq_private(seq) ((struct raw6_iter_state *)&seq->private)
static struct sock *raw6_get_first(struct seq_file *seq)
{
struct sock *sk = NULL;
struct raw6_iter_state* state = raw6_seq_private(seq);
for (state->bucket = 0; state->bucket < RAWV6_HTABLE_SIZE; ++state->bucket) {
sk = raw_v6_htable[state->bucket];
while (sk && sk->family != PF_INET6)
sk = sk->next;
if (sk)
break;
}
return sk;
}
static struct sock *raw6_get_next(struct seq_file *seq, struct sock *sk)
{
struct raw6_iter_state* state = raw6_seq_private(seq);
do {
sk = sk->next;
try_again:
;
} while (sk && sk->family != PF_INET6);
if (!sk && ++state->bucket < RAWV6_HTABLE_SIZE) {
sk = raw_v6_htable[state->bucket];
goto try_again;
}
return sk;
}
static struct sock *raw6_get_idx(struct seq_file *seq, loff_t pos)
{
struct sock *sk = raw6_get_first(seq);
if (sk)
while (pos && (sk = raw6_get_next(seq, sk)) != NULL)
--pos;
return pos ? NULL : sk;
}
static void *raw6_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock(&raw_v6_lock);
return *pos ? raw6_get_idx(seq, *pos) : (void *)1;
}
static void *raw6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct sock *sk;
if (v == (void *)1)
sk = raw6_get_first(seq);
else
sk = raw6_get_next(seq, v);
++*pos;
return sk;
}
static void raw6_seq_stop(struct seq_file *seq, void *v)
{
read_unlock(&raw_v6_lock);
}
static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i) static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
{ {
struct ipv6_pinfo *np = inet6_sk(sp); struct ipv6_pinfo *np = inet6_sk(sp);
struct in6_addr *dest, *src; struct in6_addr *dest, *src;
...@@ -844,9 +933,9 @@ static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i) ...@@ -844,9 +933,9 @@ static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i)
src = &np->rcv_saddr; src = &np->rcv_saddr;
destp = 0; destp = 0;
srcp = inet_sk(sp)->num; srcp = inet_sk(sp)->num;
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", "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %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,
...@@ -860,65 +949,53 @@ static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i) ...@@ -860,65 +949,53 @@ static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i)
atomic_read(&sp->refcnt), sp); atomic_read(&sp->refcnt), sp);
} }
int raw6_get_info(char *buffer, char **start, off_t offset, int length) static int raw6_seq_show(struct seq_file *seq, void *v)
{ {
int len = 0, num = 0, i; if (v == (void *)1)
off_t pos = 0; seq_printf(seq,
off_t begin; " sl "
char tmpbuf[LINE_LEN+2]; "local_address "
"remote_address "
if (offset < LINE_LEN+1) "st tx_queue rx_queue tr tm->when retrnsmt"
len += sprintf(buffer, LINE_FMT, " uid timeout inode\n");
" sl " /* 6 */ else
"local_address " /* 38 */ raw6_sock_seq_show(seq, v, raw6_seq_private(seq)->bucket);
"remote_address " /* 38 */ return 0;
"st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */ }
" uid timeout inode"); /* 21 */
/*----*/
/*144 */
pos = LINE_LEN+1;
read_lock(&raw_v6_lock);
for (i = 0; i < RAWV6_HTABLE_SIZE; i++) {
struct sock *sk;
for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) { static struct seq_operations raw6_seq_ops = {
if (sk->family != PF_INET6) .start = raw6_seq_start,
continue; .next = raw6_seq_next,
pos += LINE_LEN+1; .stop = raw6_seq_stop,
if (pos <= offset) .show = raw6_seq_show,
continue; };
get_raw6_sock(sk, tmpbuf, i);
len += sprintf(buffer+len, LINE_FMT, tmpbuf); static int raw6_seq_open(struct inode *inode, struct file *file)
if(len >= length) {
goto out; return seq_open(file, &raw6_seq_ops);
}
}
out:
read_unlock(&raw_v6_lock);
begin = len - (pos - offset);
*start = buffer + begin;
len -= begin;
if(len > length)
len = length;
if (len < 0)
len = 0;
return len;
} }
struct proto rawv6_prot = { static struct file_operations raw6_seq_fops = {
.name = "RAW", .owner = THIS_MODULE,
.close = rawv6_close, .open = raw6_seq_open,
.connect = udpv6_connect, .read = seq_read,
.disconnect = udp_disconnect, .llseek = seq_lseek,
.ioctl = rawv6_ioctl, .release = seq_release,
.init = rawv6_init_sk,
.destroy = inet6_destroy_sock,
.setsockopt = rawv6_setsockopt,
.getsockopt = rawv6_getsockopt,
.sendmsg = rawv6_sendmsg,
.recvmsg = rawv6_recvmsg,
.bind = rawv6_bind,
.backlog_rcv = rawv6_rcv_skb,
.hash = raw_v6_hash,
.unhash = raw_v6_unhash,
}; };
int __init raw6_proc_init(void)
{
struct proc_dir_entry *p = create_proc_entry("raw6", S_IRUGO, proc_net);
if (!p)
return -ENOMEM;
p->proc_fops = &raw6_seq_fops;
return 0;
}
void raw6_proc_exit(void)
{
remove_proc_entry("raw6", proc_net);
}
#endif /* CONFIG_PROC_FS */
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