Commit 7e9971e1 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

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

parent 2f647ecc
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
* Yuji SEKIYA @USAGI : Don't assign a same IPv6 * Yuji SEKIYA @USAGI : Don't assign a same IPv6
* address on a same interface. * address on a same interface.
* YOSHIFUJI Hideaki @USAGI : ARCnet support * YOSHIFUJI Hideaki @USAGI : ARCnet support
* YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to
* seq_file.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -76,6 +78,9 @@ ...@@ -76,6 +78,9 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#define IPV6_MAX_ADDRESSES 16 #define IPV6_MAX_ADDRESSES 16
/* Set to 3 to get tracing... */ /* Set to 3 to get tracing... */
...@@ -2090,57 +2095,141 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) ...@@ -2090,57 +2095,141 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int iface_proc_info(char *buffer, char **start, off_t offset, struct if6_iter_state {
int length) int bucket;
};
static inline struct inet6_ifaddr *if6_get_bucket(struct seq_file *seq, loff_t *pos)
{ {
struct inet6_ifaddr *ifp;
int i; int i;
int len = 0; struct inet6_ifaddr *ifa = NULL;
off_t pos=0; loff_t l = *pos;
off_t begin=0; struct if6_iter_state *state = seq->private;
for (i=0; i < IN6_ADDR_HSIZE; i++) { for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket)
read_lock_bh(&addrconf_hash_lock); for (i = 0, ifa = inet6_addr_lst[state->bucket]; ifa; ++i, ifa=ifa->lst_next) {
for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { if (l--)
int j; continue;
*pos = i;
goto out;
}
out:
return ifa;
}
for (j=0; j<16; j++) { static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
sprintf(buffer + len, "%02x", {
ifp->addr.s6_addr[j]); read_lock_bh(&addrconf_hash_lock);
len += 2; return *pos ? if6_get_bucket(seq, pos) : (void *)1;
} }
len += sprintf(buffer + len, static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
" %02x %02x %02x %02x %8s\n", {
ifp->idev->dev->ifindex, struct inet6_ifaddr *ifa;
ifp->prefix_len, struct if6_iter_state *state;
ifp->scope,
ifp->flags, if (v == (void *)1) {
ifp->idev->dev->name); ifa = if6_get_bucket(seq, pos);
pos=begin+len; goto out;
if(pos<offset) {
len=0;
begin=pos;
}
if(pos>offset+length) {
read_unlock_bh(&addrconf_hash_lock);
goto done;
}
}
read_unlock_bh(&addrconf_hash_lock);
} }
done: state = seq->private;
ifa = v;
ifa = ifa->lst_next;
if (ifa)
goto out;
*start=buffer+(offset-begin); if (++state->bucket >= IN6_ADDR_HSIZE)
len-=(offset-begin); goto out;
if(len>length)
len=length; *pos = 0;
if(len<0) ifa = if6_get_bucket(seq, pos);
len=0; out:
return len; ++*pos;
return ifa;
} }
static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr *ifp)
{
seq_printf(seq,
"%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n",
NIP6(ifp->addr),
ifp->idev->dev->ifindex,
ifp->prefix_len,
ifp->scope,
ifp->flags,
ifp->idev->dev->name);
}
static int if6_seq_show(struct seq_file *seq, void *v)
{
if (v == (void *)1)
return 0;
else
if6_iface_seq_show(seq, v);
return 0;
}
static void if6_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&addrconf_hash_lock);
}
static struct seq_operations if6_seq_ops = {
.start = if6_seq_start,
.next = if6_seq_next,
.show = if6_seq_show,
.stop = if6_seq_stop,
};
static int if6_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
struct if6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
memset(s, 0, sizeof(*s));
rc = seq_open(file, &if6_seq_ops);
if (rc)
goto out_kfree;
seq = file->private_data;
seq->private = s;
out:
return rc;
out_kfree:
kfree(s);
goto out;
}
static struct file_operations if6_fops = {
.owner = THIS_MODULE,
.open = if6_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_private,
};
int __init if6_proc_init(void)
{
struct proc_dir_entry *p;
int rc = 0;
p = create_proc_entry("if_inet6", S_IRUGO, proc_net);
if (p)
p->proc_fops = &if6_fops;
else
rc = -ENOMEM;
return rc;
}
void if6_proc_exit(void)
{
proc_net_remove("if_inet6");
}
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
/* /*
...@@ -2727,10 +2816,6 @@ void __init addrconf_init(void) ...@@ -2727,10 +2816,6 @@ void __init addrconf_init(void)
rtnl_unlock(); rtnl_unlock();
#endif #endif
#ifdef CONFIG_PROC_FS
proc_net_create("if_inet6", 0, iface_proc_info);
#endif
addrconf_verify(0); addrconf_verify(0);
rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
......
...@@ -87,6 +87,10 @@ extern int ipv6_misc_proc_init(void); ...@@ -87,6 +87,10 @@ extern int ipv6_misc_proc_init(void);
extern int ipv6_misc_proc_exit(void); extern int ipv6_misc_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 if6_proc_init(void);
extern void if6_proc_exit(void);
#endif #endif
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
...@@ -799,6 +803,8 @@ static int __init inet6_init(void) ...@@ -799,6 +803,8 @@ static int __init inet6_init(void)
if (!proc_net_create("anycast6", 0, anycast6_get_info)) if (!proc_net_create("anycast6", 0, anycast6_get_info))
goto proc_anycast6_fail; goto proc_anycast6_fail;
if (if6_proc_init())
goto proc_if6_fail;
#endif #endif
ipv6_netdev_notif_init(); ipv6_netdev_notif_init();
ipv6_packet_init(); ipv6_packet_init();
...@@ -820,6 +826,8 @@ static int __init inet6_init(void) ...@@ -820,6 +826,8 @@ static int __init inet6_init(void)
return 0; return 0;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_if6_fail:
proc_net_remove("anycast6");
proc_anycast6_fail: proc_anycast6_fail:
ipv6_misc_proc_exit(); ipv6_misc_proc_exit();
proc_misc6_fail: proc_misc6_fail:
...@@ -852,6 +860,7 @@ static void inet6_exit(void) ...@@ -852,6 +860,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
if6_proc_exit();
raw6_proc_exit(); raw6_proc_exit();
proc_net_remove("tcp6"); proc_net_remove("tcp6");
proc_net_remove("udp6"); proc_net_remove("udp6");
......
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