Commit ba22d84c authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji Committed by James Morris

[NET] convert /proc/net/mfilter6 to seq_file

parent f26e95cb
...@@ -2179,80 +2179,178 @@ static struct file_operations igmp6_mc_seq_fops = { ...@@ -2179,80 +2179,178 @@ static struct file_operations igmp6_mc_seq_fops = {
.release = seq_release_private, .release = seq_release_private,
}; };
static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset, struct igmp6_mcf_iter_state {
int length, int *eof, void *data)
{
off_t pos=0, begin=0;
int len=0;
int first=1;
struct net_device *dev; struct net_device *dev;
struct inet6_dev *idev;
read_lock(&dev_base_lock); struct ifmcaddr6 *im;
for (dev=dev_base; dev; dev=dev->next) { };
struct inet6_dev *idev = in6_dev_get(dev);
struct ifmcaddr6 *imc;
if (idev == NULL) #define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)&seq->private)
continue;
read_lock_bh(&idev->lock); static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
{
struct ip6_sf_list *psf = NULL;
struct ifmcaddr6 *im = NULL;
struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
for (imc=idev->mc_list; imc; imc=imc->next) { for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
struct ip6_sf_list *psf; state->dev;
unsigned long i; state->dev = state->dev->next) {
struct inet6_dev *idev;
spin_lock_bh(&imc->mca_lock); idev = in6_dev_get(state->dev);
for (psf=imc->mca_sources; psf; psf=psf->sf_next) { if (unlikely(idev == NULL))
if (first) { continue;
len += sprintf(buffer+len, "%3s %6s " read_lock_bh(&idev->lock);
"%32s %32s %6s %6s\n", "Idx", im = idev->mc_list;
"Device", "Multicast Address", if (likely(im != NULL)) {
"Source Address", "INC", "EXC"); spin_lock_bh(&im->mca_lock);
first = 0; psf = im->mca_sources;
} if (likely(psf != NULL)) {
len += sprintf(buffer+len,"%3d %6.6s ", state->im = im;
dev->ifindex, dev->name); state->idev = idev;
break;
for (i=0; i<16; i++)
len += sprintf(buffer+len, "%02x",
imc->mca_addr.s6_addr[i]);
buffer[len++] = ' ';
for (i=0; i<16; i++)
len += sprintf(buffer+len, "%02x",
psf->sf_addr.s6_addr[i]);
len += sprintf(buffer+len, " %6lu %6lu\n",
psf->sf_count[MCAST_INCLUDE],
psf->sf_count[MCAST_EXCLUDE]);
pos = begin+len;
if (pos < offset) {
len=0;
begin=pos;
}
if (pos > offset+length) {
spin_unlock_bh(&imc->mca_lock);
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
goto done;
}
} }
spin_unlock_bh(&imc->mca_lock); spin_unlock_bh(&im->mca_lock);
} }
read_unlock_bh(&idev->lock); read_unlock_bh(&idev->lock);
in6_dev_put(idev);
} }
*eof = 1; return psf;
}
done: static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_sf_list *psf)
{
struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
psf = psf->sf_next;
while (!psf) {
spin_unlock_bh(&state->im->mca_lock);
state->im = state->im->next;
while (!state->im) {
if (likely(state->idev != NULL)) {
read_unlock_bh(&state->idev->lock);
in6_dev_put(state->idev);
}
state->dev = state->dev->next;
if (!state->dev) {
state->idev = NULL;
goto out;
}
state->idev = in6_dev_get(state->dev);
if (!state->idev)
continue;
read_lock_bh(&state->idev->lock);
state->im = state->idev->mc_list;
}
if (!state->im)
break;
spin_lock_bh(&state->im->mca_lock);
psf = state->im->mca_sources;
}
out:
return psf;
}
static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos)
{
struct ip6_sf_list *psf = igmp6_mcf_get_first(seq);
if (psf)
while (pos && (psf = igmp6_mcf_get_next(seq, psf)) != NULL)
--pos;
return pos ? NULL : psf;
}
static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock(&dev_base_lock);
return *pos ? igmp6_mcf_get_idx(seq, *pos) : (void *)1;
}
static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct ip6_sf_list *psf;
if (v == (void *)1)
psf = igmp6_mcf_get_first(seq);
else
psf = igmp6_mcf_get_next(seq, v);
++*pos;
return psf;
}
static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v)
{
struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
if (likely(state->im != NULL))
spin_unlock_bh(&state->im->mca_lock);
if (likely(state->idev != NULL)) {
read_unlock_bh(&state->idev->lock);
in6_dev_put(state->idev);
}
read_unlock(&dev_base_lock); read_unlock(&dev_base_lock);
}
static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
{
struct ip6_sf_list *psf = (struct ip6_sf_list *)v;
struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
if (v == (void *)1) {
seq_printf(seq,
"%3s %6s "
"%32s %32s %6s %6s\n", "Idx",
"Device", "Multicast Address",
"Source Address", "INC", "EXC");
} else {
seq_printf(seq,
"%3d %6.6s "
"%04x%04x%04x%04x%04x%04x%04x%04x "
"%04x%04x%04x%04x%04x%04x%04x%04x "
"%6lu %6lu\n",
state->dev->ifindex, state->dev->name,
NIP6(state->im->mca_addr),
NIP6(psf->sf_addr),
psf->sf_count[MCAST_INCLUDE],
psf->sf_count[MCAST_EXCLUDE]);
}
return 0;
}
static struct seq_operations igmp6_mcf_seq_ops = {
.start = igmp6_mcf_seq_start,
.next = igmp6_mcf_seq_next,
.stop = igmp6_mcf_seq_stop,
.show = igmp6_mcf_seq_show,
};
static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
struct igmp6_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
*start=buffer+(offset-begin); rc = seq_open(file, &igmp6_mcf_seq_ops);
len-=(offset-begin); if (rc)
if(len>length) goto out_kfree;
len=length;
if (len<0) seq = file->private_data;
len=0; seq->private = s;
return len; memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
kfree(s);
goto out;
} }
static struct file_operations igmp6_mcf_seq_fops = {
.owner = THIS_MODULE,
.open = igmp6_mcf_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_private,
};
#endif #endif
int __init igmp6_init(struct net_proto_family *ops) int __init igmp6_init(struct net_proto_family *ops)
...@@ -2284,7 +2382,9 @@ int __init igmp6_init(struct net_proto_family *ops) ...@@ -2284,7 +2382,9 @@ int __init igmp6_init(struct net_proto_family *ops)
p = create_proc_entry("igmp6", S_IRUGO, proc_net); p = create_proc_entry("igmp6", S_IRUGO, proc_net);
if (p) if (p)
p->proc_fops = &igmp6_mc_seq_fops; p->proc_fops = &igmp6_mc_seq_fops;
create_proc_read_entry("net/mcfilter6", 0, 0, ip6_mcf_read_proc, NULL); p = create_proc_entry("mcfilter6", S_IRUGO, proc_net);
if (p)
p->proc_fops = &igmp6_mcf_seq_fops;
#endif #endif
return 0; return 0;
...@@ -2295,6 +2395,7 @@ void igmp6_cleanup(void) ...@@ -2295,6 +2395,7 @@ void igmp6_cleanup(void)
sock_release(igmp6_socket); sock_release(igmp6_socket);
igmp6_socket = NULL; /* for safety */ igmp6_socket = NULL; /* for safety */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_net_remove("mcfilter6");
proc_net_remove("igmp6"); proc_net_remove("igmp6");
#endif #endif
} }
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