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

[IPV4/6]: Common UDP procfs infrastructure.

parent 91396556
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/snmp.h> #include <net/snmp.h>
#include <linux/seq_file.h>
#define UDP_HTABLE_SIZE 128 #define UDP_HTABLE_SIZE 128
...@@ -77,4 +78,21 @@ DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); ...@@ -77,4 +78,21 @@ DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field) #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field) #define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field)
/* /proc */
struct udp_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 udp_iter_state {
sa_family_t family;
int bucket;
struct seq_operations seq_ops;
};
extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
#endif /* _UDP_H */ #endif /* _UDP_H */
...@@ -1239,8 +1239,8 @@ extern int raw_proc_init(void); ...@@ -1239,8 +1239,8 @@ extern int raw_proc_init(void);
extern void raw_proc_exit(void); extern void raw_proc_exit(void);
extern int tcp_proc_init(void); extern int tcp_proc_init(void);
extern void tcp_proc_exit(void); extern void tcp_proc_exit(void);
extern int udp_proc_init(void); extern int udp4_proc_init(void);
extern void udp_proc_exit(void); extern void udp4_proc_exit(void);
int __init ipv4_proc_init(void) int __init ipv4_proc_init(void)
{ {
...@@ -1250,7 +1250,7 @@ int __init ipv4_proc_init(void) ...@@ -1250,7 +1250,7 @@ int __init ipv4_proc_init(void)
goto out_raw; goto out_raw;
if (tcp_proc_init()) if (tcp_proc_init())
goto out_tcp; goto out_tcp;
if (udp_proc_init()) if (udp4_proc_init())
goto out_udp; goto out_udp;
if (fib_proc_init()) if (fib_proc_init())
goto out_fib; goto out_fib;
...@@ -1261,7 +1261,7 @@ int __init ipv4_proc_init(void) ...@@ -1261,7 +1261,7 @@ int __init ipv4_proc_init(void)
out_misc: out_misc:
fib_proc_exit(); fib_proc_exit();
out_fib: out_fib:
udp_proc_exit(); udp4_proc_exit();
out_udp: out_udp:
tcp_proc_exit(); tcp_proc_exit();
out_tcp: out_tcp:
......
...@@ -1349,10 +1349,6 @@ struct proto udp_prot = { ...@@ -1349,10 +1349,6 @@ struct proto udp_prot = {
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct udp_iter_state {
int bucket;
};
static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos) static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos)
{ {
int i; int i;
...@@ -1362,7 +1358,7 @@ static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos) ...@@ -1362,7 +1358,7 @@ static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos)
for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket)
for (i = 0, sk = udp_hash[state->bucket]; sk; ++i, sk = sk->next) { for (i = 0, sk = udp_hash[state->bucket]; sk; ++i, sk = sk->next) {
if (sk->family != PF_INET) if (sk->family != state->family)
continue; continue;
if (l--) if (l--)
continue; continue;
...@@ -1389,15 +1385,16 @@ static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -1389,15 +1385,16 @@ static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
goto out; goto out;
} }
state = seq->private;
sk = v; sk = v;
sk = sk->next; sk = sk->next;
for (; sk; sk = sk->next) { for (; sk; sk = sk->next) {
if (sk->family == AF_INET) if (sk->family == state->family)
goto out; goto out;
} }
state = seq->private;
if (++state->bucket >= UDP_HTABLE_SIZE) if (++state->bucket >= UDP_HTABLE_SIZE)
goto out; goto out;
...@@ -1413,7 +1410,68 @@ static void udp_seq_stop(struct seq_file *seq, void *v) ...@@ -1413,7 +1410,68 @@ static void udp_seq_stop(struct seq_file *seq, void *v)
read_unlock(&udp_hash_lock); read_unlock(&udp_hash_lock);
} }
static void udp_format_sock(struct sock *sp, char *tmpbuf, int bucket) static int udp_seq_open(struct inode *inode, struct file *file)
{
struct udp_seq_afinfo *afinfo = PDE(inode)->data;
struct seq_file *seq;
int rc = -ENOMEM;
struct udp_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 = udp_seq_start;
s->seq_ops.next = udp_seq_next;
s->seq_ops.show = afinfo->seq_show;
s->seq_ops.stop = udp_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 udp_proc_register(struct udp_seq_afinfo *afinfo)
{
struct proc_dir_entry *p;
int rc = 0;
if (!afinfo)
return -EINVAL;
afinfo->seq_fops->owner = afinfo->owner;
afinfo->seq_fops->open = udp_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 udp_proc_unregister(struct udp_seq_afinfo *afinfo)
{
if (!afinfo)
return;
remove_proc_entry(afinfo->name, proc_net);
memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
}
/* ------------------------------------------------------------------------ */
static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
{ {
struct inet_opt *inet = inet_sk(sp); struct inet_opt *inet = inet_sk(sp);
unsigned int dest = inet->daddr; unsigned int dest = inet->daddr;
...@@ -1429,7 +1487,7 @@ static void udp_format_sock(struct sock *sp, char *tmpbuf, int bucket) ...@@ -1429,7 +1487,7 @@ static void udp_format_sock(struct sock *sp, char *tmpbuf, int bucket)
atomic_read(&sp->refcnt), sp); atomic_read(&sp->refcnt), sp);
} }
static int udp_seq_show(struct seq_file *seq, void *v) static int udp4_seq_show(struct seq_file *seq, void *v)
{ {
if (v == (void *)1) if (v == (void *)1)
seq_printf(seq, "%-127s\n", seq_printf(seq, "%-127s\n",
...@@ -1440,68 +1498,29 @@ static int udp_seq_show(struct seq_file *seq, void *v) ...@@ -1440,68 +1498,29 @@ static int udp_seq_show(struct seq_file *seq, void *v)
char tmpbuf[129]; char tmpbuf[129];
struct udp_iter_state *state = seq->private; struct udp_iter_state *state = seq->private;
udp_format_sock(v, tmpbuf, state->bucket); udp4_format_sock(v, tmpbuf, state->bucket);
seq_printf(seq, "%-127s\n", tmpbuf); seq_printf(seq, "%-127s\n", tmpbuf);
} }
return 0; return 0;
} }
/* ------------------------------------------------------------------------ */
static struct seq_operations udp_seq_ops = {
.start = udp_seq_start,
.next = udp_seq_next,
.stop = udp_seq_stop,
.show = udp_seq_show,
};
static int udp_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
rc = seq_open(file, &udp_seq_ops);
if (rc)
goto out_kfree;
seq = file->private_data; /* ------------------------------------------------------------------------ */
seq->private = s; static struct file_operations udp4_seq_fops;
memset(s, 0, sizeof(*s)); static struct udp_seq_afinfo udp4_seq_afinfo = {
out:
return rc;
out_kfree:
kfree(s);
goto out;
}
static struct file_operations udp_seq_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = udp_seq_open, .name = "udp",
.read = seq_read, .family = AF_INET,
.llseek = seq_lseek, .seq_show = udp4_seq_show,
.release = seq_release_private, .seq_fops = &udp4_seq_fops,
}; };
/* ------------------------------------------------------------------------ */ int __init udp4_proc_init(void)
int __init udp_proc_init(void)
{ {
struct proc_dir_entry *p; return udp_proc_register(&udp4_seq_afinfo);
int rc = 0;
p = create_proc_entry("udp", S_IRUGO, proc_net);
if (p)
p->proc_fops = &udp_seq_fops;
else
rc = -ENOMEM;
return rc;
} }
void __init udp_proc_exit(void) void udp4_proc_exit(void)
{ {
remove_proc_entry("udp", proc_net); udp_proc_unregister(&udp4_seq_afinfo);
} }
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
...@@ -281,6 +281,12 @@ EXPORT_SYMBOL(devinet_ioctl); ...@@ -281,6 +281,12 @@ EXPORT_SYMBOL(devinet_ioctl);
EXPORT_SYMBOL(register_inetaddr_notifier); EXPORT_SYMBOL(register_inetaddr_notifier);
EXPORT_SYMBOL(unregister_inetaddr_notifier); EXPORT_SYMBOL(unregister_inetaddr_notifier);
/* proc */
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(udp_proc_register);
EXPORT_SYMBOL(udp_proc_unregister);
#endif
/* needed for ip_gre -cw */ /* needed for ip_gre -cw */
EXPORT_SYMBOL(ip_statistics); EXPORT_SYMBOL(ip_statistics);
......
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