o ipv4: convert /proc/net/route to seq_file

parent 414abb51
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <net/flow.h> #include <net/flow.h>
#include <linux/seq_file.h>
struct kern_rta struct kern_rta
{ {
...@@ -128,8 +129,7 @@ struct fib_table ...@@ -128,8 +129,7 @@ struct fib_table
int (*tb_dump)(struct fib_table *table, struct sk_buff *skb, int (*tb_dump)(struct fib_table *table, struct sk_buff *skb,
struct netlink_callback *cb); struct netlink_callback *cb);
int (*tb_flush)(struct fib_table *table); int (*tb_flush)(struct fib_table *table);
int (*tb_get_info)(struct fib_table *table, char *buf, int (*tb_seq_show)(struct fib_table *table, struct seq_file *seq);
int first, int count);
void (*tb_select_default)(struct fib_table *table, void (*tb_select_default)(struct fib_table *table,
const struct flowi *flp, struct fib_result *res); const struct flowi *flp, struct fib_result *res);
...@@ -138,14 +138,14 @@ struct fib_table ...@@ -138,14 +138,14 @@ struct fib_table
#ifndef CONFIG_IP_MULTIPLE_TABLES #ifndef CONFIG_IP_MULTIPLE_TABLES
extern struct fib_table *local_table; extern struct fib_table *ip_fib_local_table;
extern struct fib_table *main_table; extern struct fib_table *ip_fib_main_table;
static inline struct fib_table *fib_get_table(int id) static inline struct fib_table *fib_get_table(int id)
{ {
if (id != RT_TABLE_LOCAL) if (id != RT_TABLE_LOCAL)
return main_table; return ip_fib_main_table;
return local_table; return ip_fib_local_table;
} }
static inline struct fib_table *fib_new_table(int id) static inline struct fib_table *fib_new_table(int id)
...@@ -155,8 +155,8 @@ static inline struct fib_table *fib_new_table(int id) ...@@ -155,8 +155,8 @@ static inline struct fib_table *fib_new_table(int id)
static inline int fib_lookup(const struct flowi *flp, struct fib_result *res) static inline int fib_lookup(const struct flowi *flp, struct fib_result *res)
{ {
if (local_table->tb_lookup(local_table, flp, res) && if (ip_fib_local_table->tb_lookup(ip_fib_local_table, flp, res) &&
main_table->tb_lookup(main_table, flp, res)) ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res))
return -ENETUNREACH; return -ENETUNREACH;
return 0; return 0;
} }
...@@ -164,12 +164,12 @@ static inline int fib_lookup(const struct flowi *flp, struct fib_result *res) ...@@ -164,12 +164,12 @@ static inline int fib_lookup(const struct flowi *flp, struct fib_result *res)
static inline void fib_select_default(const struct flowi *flp, struct fib_result *res) static inline void fib_select_default(const struct flowi *flp, struct fib_result *res)
{ {
if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
main_table->tb_select_default(main_table, flp, res); ip_fib_main_table->tb_select_default(ip_fib_main_table, flp, res);
} }
#else /* CONFIG_IP_MULTIPLE_TABLES */ #else /* CONFIG_IP_MULTIPLE_TABLES */
#define local_table (fib_tables[RT_TABLE_LOCAL]) #define ip_fib_local_table (fib_tables[RT_TABLE_LOCAL])
#define main_table (fib_tables[RT_TABLE_MAIN]) #define ip_fib_main_table (fib_tables[RT_TABLE_MAIN])
extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; extern struct fib_table * fib_tables[RT_TABLE_MAX+1];
extern int fib_lookup(const struct flowi *flp, struct fib_result *res); extern int fib_lookup(const struct flowi *flp, struct fib_result *res);
...@@ -222,7 +222,8 @@ extern int fib_sync_down(u32 local, struct net_device *dev, int force); ...@@ -222,7 +222,8 @@ extern int fib_sync_down(u32 local, struct net_device *dev, int force);
extern int fib_sync_up(struct net_device *dev); extern int fib_sync_up(struct net_device *dev);
extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
struct kern_rta *rta, struct rtentry *r); struct kern_rta *rta, struct rtentry *r);
extern void fib_node_get_info(int type, int dead, struct fib_info *fi, u32 prefix, u32 mask, char *buffer); extern void fib_node_seq_show(struct seq_file *seq, int type, int dead,
struct fib_info *fi, u32 prefix, u32 mask);
extern u32 __fib_res_prefsrc(struct fib_result *res); extern u32 __fib_res_prefsrc(struct fib_result *res);
/* Exported by fib_hash.c */ /* Exported by fib_hash.c */
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <linux/inet.h> #include <linux/inet.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -51,8 +50,8 @@ ...@@ -51,8 +50,8 @@
#define RT_TABLE_MIN RT_TABLE_MAIN #define RT_TABLE_MIN RT_TABLE_MAIN
struct fib_table *local_table; struct fib_table *ip_fib_local_table;
struct fib_table *main_table; struct fib_table *ip_fib_main_table;
#else #else
...@@ -88,56 +87,14 @@ void fib_flush(void) ...@@ -88,56 +87,14 @@ void fib_flush(void)
flushed += tb->tb_flush(tb); flushed += tb->tb_flush(tb);
} }
#else /* CONFIG_IP_MULTIPLE_TABLES */ #else /* CONFIG_IP_MULTIPLE_TABLES */
flushed += main_table->tb_flush(main_table); flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
flushed += local_table->tb_flush(local_table); flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
#endif /* CONFIG_IP_MULTIPLE_TABLES */ #endif /* CONFIG_IP_MULTIPLE_TABLES */
if (flushed) if (flushed)
rt_cache_flush(-1); rt_cache_flush(-1);
} }
#ifdef CONFIG_PROC_FS
/*
* Called from the PROCfs module. This outputs /proc/net/route.
*
* It always works in backward compatibility mode.
* The format of the file is not supposed to be changed.
*/
static int
fib_get_procinfo(char *buffer, char **start, off_t offset, int length)
{
int first = offset/128;
char *ptr = buffer;
int count = (length+127)/128;
int len;
*start = buffer + offset%128;
if (--first < 0) {
sprintf(buffer, "%-127s\n", "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT");
--count;
ptr += 128;
first = 0;
}
if (main_table && count > 0) {
int n = main_table->tb_get_info(main_table, ptr, first, count);
count -= n;
ptr += n*128;
}
len = ptr - *start;
if (len >= length)
return length;
if (len >= 0)
return len;
return 0;
}
#endif /* CONFIG_PROC_FS */
/* /*
* Find the first device with a given source address. * Find the first device with a given source address.
*/ */
...@@ -152,9 +109,9 @@ struct net_device * ip_dev_find(u32 addr) ...@@ -152,9 +109,9 @@ struct net_device * ip_dev_find(u32 addr)
res.r = NULL; res.r = NULL;
#endif #endif
if (!local_table || local_table->tb_lookup(local_table, &fl, &res)) { if (!ip_fib_local_table ||
ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res))
return NULL; return NULL;
}
if (res.type != RTN_LOCAL) if (res.type != RTN_LOCAL)
goto out; goto out;
dev = FIB_RES_DEV(res); dev = FIB_RES_DEV(res);
...@@ -181,9 +138,10 @@ unsigned inet_addr_type(u32 addr) ...@@ -181,9 +138,10 @@ unsigned inet_addr_type(u32 addr)
res.r = NULL; res.r = NULL;
#endif #endif
if (local_table) { if (ip_fib_local_table) {
ret = RTN_UNICAST; ret = RTN_UNICAST;
if (local_table->tb_lookup(local_table, &fl, &res) == 0) { if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
&fl, &res)) {
ret = res.type; ret = res.type;
fib_res_put(&res); fib_res_put(&res);
} }
...@@ -636,13 +594,9 @@ struct notifier_block fib_netdev_notifier = { ...@@ -636,13 +594,9 @@ struct notifier_block fib_netdev_notifier = {
void __init ip_fib_init(void) void __init ip_fib_init(void)
{ {
#ifdef CONFIG_PROC_FS
proc_net_create("route",0,fib_get_procinfo);
#endif /* CONFIG_PROC_FS */
#ifndef CONFIG_IP_MULTIPLE_TABLES #ifndef CONFIG_IP_MULTIPLE_TABLES
local_table = fib_hash_init(RT_TABLE_LOCAL); ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
main_table = fib_hash_init(RT_TABLE_MAIN); ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
#else #else
fib_rules_init(); fib_rules_init();
#endif #endif
......
...@@ -747,46 +747,31 @@ static int fn_hash_flush(struct fib_table *tb) ...@@ -747,46 +747,31 @@ static int fn_hash_flush(struct fib_table *tb)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int fn_hash_get_info(struct fib_table *tb, char *buffer, int first, int count) static int fn_hash_seq_show(struct fib_table *tb, struct seq_file *seq)
{ {
struct fn_hash *table = (struct fn_hash*)tb->tb_data; struct fn_hash *table = (struct fn_hash *)tb->tb_data;
struct fn_zone *fz; struct fn_zone *fz;
int pos = 0;
int n = 0;
read_lock(&fib_hash_lock); read_lock(&fib_hash_lock);
for (fz=table->fn_zone_list; fz; fz = fz->fz_next) { for (fz = table->fn_zone_list; fz; fz = fz->fz_next) {
int i; int i;
struct fib_node *f; struct fib_node *f;
int maxslot = fz->fz_divisor; int maxslot = fz->fz_divisor;
struct fib_node **fp = fz->fz_hash; struct fib_node **fp = fz->fz_hash;
if (fz->fz_nent == 0) if (!fz->fz_nent)
continue; continue;
if (pos + fz->fz_nent <= first) { for (i = 0; i < maxslot; i++, fp++)
pos += fz->fz_nent; for (f = *fp; f; f = f->fn_next)
continue; fib_node_seq_show(seq, f->fn_type,
} f->fn_state & FN_S_ZOMBIE,
for (i=0; i < maxslot; i++, fp++) {
for (f = *fp; f; f = f->fn_next) {
if (++pos <= first)
continue;
fib_node_get_info(f->fn_type,
f->fn_state&FN_S_ZOMBIE,
FIB_INFO(f), FIB_INFO(f),
fz_prefix(f->fn_key, fz), fz_prefix(f->fn_key, fz),
FZ_MASK(fz), buffer); FZ_MASK(fz));
buffer += 128;
if (++n >= count)
goto out;
}
}
} }
out:
read_unlock(&fib_hash_lock); read_unlock(&fib_hash_lock);
return n; return 0;
} }
#endif #endif
...@@ -913,7 +898,7 @@ struct fib_table * __init fib_hash_init(int id) ...@@ -913,7 +898,7 @@ struct fib_table * __init fib_hash_init(int id)
tb->tb_select_default = fn_hash_select_default; tb->tb_select_default = fn_hash_select_default;
tb->tb_dump = fn_hash_dump; tb->tb_dump = fn_hash_dump;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
tb->tb_get_info = fn_hash_get_info; tb->tb_seq_show = fn_hash_seq_show;
#endif #endif
memset(tb->tb_data, 0, sizeof(struct fn_hash)); memset(tb->tb_data, 0, sizeof(struct fn_hash));
return tb; return tb;
......
...@@ -1017,24 +1017,24 @@ static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi ...@@ -1017,24 +1017,24 @@ static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi
return flags; return flags;
} }
void fib_node_get_info(int type, int dead, struct fib_info *fi, u32 prefix, u32 mask, char *buffer) void fib_node_seq_show(struct seq_file *seq, int type, int dead,
struct fib_info *fi, u32 prefix, u32 mask)
{ {
int len; char bf[128];
unsigned flags = fib_flag_trans(type, dead, mask, fi); unsigned flags = fib_flag_trans(type, dead, mask, fi);
if (fi) { if (fi)
len = sprintf(buffer, "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", snprintf(bf, sizeof(bf),
fi->fib_dev ? fi->fib_dev->name : "*", prefix, "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority, fi->fib_dev ? fi->fib_dev->name : "*", prefix,
mask, fi->fib_advmss+40, fi->fib_window, fi->fib_rtt>>3); fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
} else { mask, fi->fib_advmss + 40, fi->fib_window,
len = sprintf(buffer, "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", fi->fib_rtt >> 3);
prefix, 0, else
flags, 0, 0, 0, snprintf(bf, sizeof(bf),
mask, 0, 0, 0); "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
} prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0);
memset(buffer+len, ' ', 127-len); seq_printf(seq, "%-127s\n", bf);
buffer[127] = '\n';
} }
#endif #endif
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/neighbour.h> #include <net/neighbour.h>
#include <net/arp.h> #include <net/arp.h>
#include <linux/rtnetlink.h>
#include <linux/route.h>
#include <net/ip_fib.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
...@@ -30,6 +33,8 @@ extern int udp_get_info(char *, char **, off_t, int); ...@@ -30,6 +33,8 @@ extern int udp_get_info(char *, char **, off_t, int);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#ifdef CONFIG_AX25 #ifdef CONFIG_AX25
/* ------------------------------------------------------------------------ */
/* /*
* ax25 -> ASCII conversion * ax25 -> ASCII conversion
*/ */
...@@ -159,6 +164,40 @@ static int arp_seq_show(struct seq_file *seq, void *v) ...@@ -159,6 +164,40 @@ static int arp_seq_show(struct seq_file *seq, void *v)
return 0; return 0;
} }
/* ------------------------------------------------------------------------ */
static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
{
return *pos ? NULL : (void *)1;
}
static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
return NULL;
}
static void fib_seq_stop(struct seq_file *seq, void *v)
{
}
/*
* This outputs /proc/net/route.
*
* It always works in backward compatibility mode.
* The format of the file is not supposed to be changed.
*/
static int fib_seq_show(struct seq_file *seq, void *v)
{
seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
"\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
"\tWindow\tIRTT");
if (ip_fib_main_table)
ip_fib_main_table->tb_seq_show(ip_fib_main_table, seq);
return 0;
}
/* ------------------------------------------------------------------------ */
struct seq_operations arp_seq_ops = { struct seq_operations arp_seq_ops = {
.start = arp_seq_start, .start = arp_seq_start,
.next = arp_seq_next, .next = arp_seq_next,
...@@ -166,11 +205,23 @@ struct seq_operations arp_seq_ops = { ...@@ -166,11 +205,23 @@ struct seq_operations arp_seq_ops = {
.show = arp_seq_show, .show = arp_seq_show,
}; };
struct seq_operations fib_seq_ops = {
.start = fib_seq_start,
.next = fib_seq_next,
.stop = fib_seq_stop,
.show = fib_seq_show,
};
static int arp_seq_open(struct inode *inode, struct file *file) static int arp_seq_open(struct inode *inode, struct file *file)
{ {
return seq_open(file, &arp_seq_ops); return seq_open(file, &arp_seq_ops);
} }
static int fib_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &fib_seq_ops);
}
static struct file_operations arp_seq_fops = { static struct file_operations arp_seq_fops = {
.open = arp_seq_open, .open = arp_seq_open,
.read = seq_read, .read = seq_read,
...@@ -178,6 +229,15 @@ static struct file_operations arp_seq_fops = { ...@@ -178,6 +229,15 @@ static struct file_operations arp_seq_fops = {
.release = seq_release, .release = seq_release,
}; };
static struct file_operations fib_seq_fops = {
.open = fib_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
/* ------------------------------------------------------------------------ */
int __init ipv4_proc_init(void) int __init ipv4_proc_init(void)
{ {
struct proc_dir_entry *p; struct proc_dir_entry *p;
...@@ -205,8 +265,15 @@ int __init ipv4_proc_init(void) ...@@ -205,8 +265,15 @@ int __init ipv4_proc_init(void)
if (!p) if (!p)
goto out_arp; goto out_arp;
p->proc_fops = &arp_seq_fops; p->proc_fops = &arp_seq_fops;
p = create_proc_entry("route", S_IRUGO, proc_net);
if (!p)
goto out_route;
p->proc_fops = &fib_seq_fops;
out: out:
return rc; return rc;
out_route:
remove_proc_entry("route", proc_net);
out_arp: out_arp:
proc_net_remove("udp"); proc_net_remove("udp");
out_udp: out_udp:
......
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