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

parent 414abb51
......@@ -18,6 +18,7 @@
#include <linux/config.h>
#include <net/flow.h>
#include <linux/seq_file.h>
struct kern_rta
{
......@@ -128,8 +129,7 @@ struct fib_table
int (*tb_dump)(struct fib_table *table, struct sk_buff *skb,
struct netlink_callback *cb);
int (*tb_flush)(struct fib_table *table);
int (*tb_get_info)(struct fib_table *table, char *buf,
int first, int count);
int (*tb_seq_show)(struct fib_table *table, struct seq_file *seq);
void (*tb_select_default)(struct fib_table *table,
const struct flowi *flp, struct fib_result *res);
......@@ -138,14 +138,14 @@ struct fib_table
#ifndef CONFIG_IP_MULTIPLE_TABLES
extern struct fib_table *local_table;
extern struct fib_table *main_table;
extern struct fib_table *ip_fib_local_table;
extern struct fib_table *ip_fib_main_table;
static inline struct fib_table *fib_get_table(int id)
{
if (id != RT_TABLE_LOCAL)
return main_table;
return local_table;
return ip_fib_main_table;
return ip_fib_local_table;
}
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)
{
if (local_table->tb_lookup(local_table, flp, res) &&
main_table->tb_lookup(main_table, flp, res))
if (ip_fib_local_table->tb_lookup(ip_fib_local_table, flp, res) &&
ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res))
return -ENETUNREACH;
return 0;
}
......@@ -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)
{
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 */
#define local_table (fib_tables[RT_TABLE_LOCAL])
#define main_table (fib_tables[RT_TABLE_MAIN])
#define ip_fib_local_table (fib_tables[RT_TABLE_LOCAL])
#define ip_fib_main_table (fib_tables[RT_TABLE_MAIN])
extern struct fib_table * fib_tables[RT_TABLE_MAX+1];
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);
extern int fib_sync_up(struct net_device *dev);
extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
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);
/* Exported by fib_hash.c */
......
......@@ -31,7 +31,6 @@
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/init.h>
......@@ -51,8 +50,8 @@
#define RT_TABLE_MIN RT_TABLE_MAIN
struct fib_table *local_table;
struct fib_table *main_table;
struct fib_table *ip_fib_local_table;
struct fib_table *ip_fib_main_table;
#else
......@@ -88,56 +87,14 @@ void fib_flush(void)
flushed += tb->tb_flush(tb);
}
#else /* CONFIG_IP_MULTIPLE_TABLES */
flushed += main_table->tb_flush(main_table);
flushed += local_table->tb_flush(local_table);
flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
#endif /* CONFIG_IP_MULTIPLE_TABLES */
if (flushed)
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.
*/
......@@ -152,9 +109,9 @@ struct net_device * ip_dev_find(u32 addr)
res.r = NULL;
#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;
}
if (res.type != RTN_LOCAL)
goto out;
dev = FIB_RES_DEV(res);
......@@ -181,9 +138,10 @@ unsigned inet_addr_type(u32 addr)
res.r = NULL;
#endif
if (local_table) {
if (ip_fib_local_table) {
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;
fib_res_put(&res);
}
......@@ -636,13 +594,9 @@ struct notifier_block fib_netdev_notifier = {
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
local_table = fib_hash_init(RT_TABLE_LOCAL);
main_table = fib_hash_init(RT_TABLE_MAIN);
ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
#else
fib_rules_init();
#endif
......
......@@ -747,46 +747,31 @@ static int fn_hash_flush(struct fib_table *tb)
#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;
int pos = 0;
int n = 0;
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;
struct fib_node *f;
int maxslot = fz->fz_divisor;
struct fib_node **fp = fz->fz_hash;
if (fz->fz_nent == 0)
continue;
if (pos + fz->fz_nent <= first) {
pos += fz->fz_nent;
if (!fz->fz_nent)
continue;
}
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,
for (i = 0; i < maxslot; i++, fp++)
for (f = *fp; f; f = f->fn_next)
fib_node_seq_show(seq, f->fn_type,
f->fn_state & FN_S_ZOMBIE,
FIB_INFO(f),
fz_prefix(f->fn_key, fz),
FZ_MASK(fz), buffer);
buffer += 128;
if (++n >= count)
goto out;
}
}
FZ_MASK(fz));
}
out:
read_unlock(&fib_hash_lock);
return n;
return 0;
}
#endif
......@@ -913,7 +898,7 @@ struct fib_table * __init fib_hash_init(int id)
tb->tb_select_default = fn_hash_select_default;
tb->tb_dump = fn_hash_dump;
#ifdef CONFIG_PROC_FS
tb->tb_get_info = fn_hash_get_info;
tb->tb_seq_show = fn_hash_seq_show;
#endif
memset(tb->tb_data, 0, sizeof(struct fn_hash));
return tb;
......
......@@ -1017,24 +1017,24 @@ static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi
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);
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",
if (fi)
snprintf(bf, sizeof(bf),
"%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
fi->fib_dev ? fi->fib_dev->name : "*", prefix,
fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
mask, fi->fib_advmss+40, fi->fib_window, fi->fib_rtt>>3);
} else {
len = sprintf(buffer, "*\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);
buffer[127] = '\n';
mask, fi->fib_advmss + 40, fi->fib_window,
fi->fib_rtt >> 3);
else
snprintf(bf, sizeof(bf),
"*\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);
seq_printf(seq, "%-127s\n", bf);
}
#endif
......@@ -18,6 +18,9 @@
#include <linux/netdevice.h>
#include <net/neighbour.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/proc_fs.h>
......@@ -30,6 +33,8 @@ extern int udp_get_info(char *, char **, off_t, int);
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_AX25
/* ------------------------------------------------------------------------ */
/*
* ax25 -> ASCII conversion
*/
......@@ -159,6 +164,40 @@ static int arp_seq_show(struct seq_file *seq, void *v)
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 = {
.start = arp_seq_start,
.next = arp_seq_next,
......@@ -166,11 +205,23 @@ struct seq_operations arp_seq_ops = {
.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)
{
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 = {
.open = arp_seq_open,
.read = seq_read,
......@@ -178,6 +229,15 @@ static struct file_operations arp_seq_fops = {
.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)
{
struct proc_dir_entry *p;
......@@ -205,8 +265,15 @@ int __init ipv4_proc_init(void)
if (!p)
goto out_arp;
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:
return rc;
out_route:
remove_proc_entry("route", proc_net);
out_arp:
proc_net_remove("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