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)
for (i = 0, ifa = inet6_addr_lst[state->bucket]; ifa; ++i, ifa=ifa->lst_next) {
if (l--)
continue;
*pos = i;
goto out;
}
out:
return ifa;
}
static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock_bh(&addrconf_hash_lock); read_lock_bh(&addrconf_hash_lock);
for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { return *pos ? if6_get_bucket(seq, pos) : (void *)1;
int j; }
static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct inet6_ifaddr *ifa;
struct if6_iter_state *state;
for (j=0; j<16; j++) { if (v == (void *)1) {
sprintf(buffer + len, "%02x", ifa = if6_get_bucket(seq, pos);
ifp->addr.s6_addr[j]); goto out;
len += 2;
} }
len += sprintf(buffer + len, state = seq->private;
" %02x %02x %02x %02x %8s\n",
ifa = v;
ifa = ifa->lst_next;
if (ifa)
goto out;
if (++state->bucket >= IN6_ADDR_HSIZE)
goto out;
*pos = 0;
ifa = if6_get_bucket(seq, pos);
out:
++*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->idev->dev->ifindex,
ifp->prefix_len, ifp->prefix_len,
ifp->scope, ifp->scope,
ifp->flags, ifp->flags,
ifp->idev->dev->name); ifp->idev->dev->name);
pos=begin+len; }
if(pos<offset) {
len=0; static int if6_seq_show(struct seq_file *seq, void *v)
begin=pos; {
} if (v == (void *)1)
if(pos>offset+length) { return 0;
read_unlock_bh(&addrconf_hash_lock); else
goto done; 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); read_unlock_bh(&addrconf_hash_lock);
} }
done: 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);
*start=buffer+(offset-begin); if (!s)
len-=(offset-begin); goto out;
if(len>length) memset(s, 0, sizeof(*s));
len=length;
if(len<0) rc = seq_open(file, &if6_seq_ops);
len=0; if (rc)
return len; 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