Commit d8cd63fa authored by David S. Miller's avatar David S. Miller

Merge master.kernel.org:/home/acme/BK/ip-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents a6805352 ff5704f6
......@@ -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,10 @@
#include <linux/netdevice.h>
#include <net/neighbour.h>
#include <net/arp.h>
#include <net/udp.h>
#include <linux/rtnetlink.h>
#include <linux/route.h>
#include <net/ip_fib.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
......@@ -26,14 +30,15 @@ extern int snmp_get_info(char *, char **, off_t, int);
extern int netstat_get_info(char *, char **, off_t, int);
extern int afinet_get_info(char *, char **, off_t, int);
extern int tcp_get_info(char *, char **, off_t, int);
extern int udp_get_info(char *, char **, off_t, int);
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_AX25
/* ------------------------------------------------------------------------ */
/*
* ax25 -> ASCII conversion
*/
char *ax2asc2(ax25_address *a, char *buf)
static char *ax2asc2(ax25_address *a, char *buf)
{
char c, *s;
int n;
......@@ -159,18 +164,130 @@ static int arp_seq_show(struct seq_file *seq, void *v)
return 0;
}
struct seq_operations arp_seq_ops = {
/* ------------------------------------------------------------------------ */
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;
}
/* ------------------------------------------------------------------------ */
static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock(&udp_hash_lock);
return (void *)(unsigned long)++*pos;
}
static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
return (void *)(unsigned long)((++*pos) >=
(UDP_HTABLE_SIZE - 1) ? 0 : *pos);
}
static void udp_seq_stop(struct seq_file *seq, void *v)
{
read_unlock(&udp_hash_lock);
}
static void udp_format_sock(struct sock *sp, char *tmpbuf, int i)
{
struct inet_opt *inet = inet_sk(sp);
unsigned int dest = inet->daddr;
unsigned int src = inet->rcv_saddr;
__u16 destp = ntohs(inet->dport);
__u16 srcp = ntohs(inet->sport);
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
i, src, srcp, dest, destp, sp->state,
atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
atomic_read(&sp->refcnt), sp);
}
static int udp_seq_show(struct seq_file *seq, void *v)
{
char tmpbuf[129];
struct sock *sk;
unsigned long l = (unsigned long)v - 1;
if (!l)
seq_printf(seq, "%-127s\n",
" sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout inode");
for (sk = udp_hash[l]; sk; sk = sk->next) {
if (sk->family != PF_INET)
continue;
udp_format_sock(sk, tmpbuf, l);
seq_printf(seq, "%-127s\n", tmpbuf);
}
return 0;
}
/* ------------------------------------------------------------------------ */
static struct seq_operations arp_seq_ops = {
.start = arp_seq_start,
.next = arp_seq_next,
.stop = arp_seq_stop,
.show = arp_seq_show,
};
static struct seq_operations fib_seq_ops = {
.start = fib_seq_start,
.next = fib_seq_next,
.stop = fib_seq_stop,
.show = fib_seq_show,
};
static struct seq_operations udp_seq_ops = {
.start = udp_seq_start,
.next = udp_seq_next,
.stop = udp_seq_stop,
.show = udp_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 int udp_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &udp_seq_ops);
}
static struct file_operations arp_seq_fops = {
.open = arp_seq_open,
.read = seq_read,
......@@ -178,6 +295,22 @@ 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,
};
static struct file_operations udp_seq_fops = {
.open = udp_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
/* ------------------------------------------------------------------------ */
int __init ipv4_proc_init(void)
{
struct proc_dir_entry *p;
......@@ -198,17 +331,26 @@ int __init ipv4_proc_init(void)
if (!proc_net_create("tcp", 0, tcp_get_info))
goto out_tcp;
if (!proc_net_create("udp", 0, udp_get_info))
p = create_proc_entry("udp", S_IRUGO, proc_net);
if (!p)
goto out_udp;
p->proc_fops = &udp_seq_fops;
p = create_proc_entry("arp", S_IRUGO, proc_net);
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");
remove_proc_entry("udp", proc_net);
out_udp:
proc_net_remove("tcp");
out_tcp:
......
......@@ -61,6 +61,7 @@
* return ENOTCONN for unconnected sockets (POSIX)
* Janos Farkas : don't deliver multi/broadcasts to a different
* bound-to-device socket
* Arnaldo C. Melo : move proc routines to ip_proc.c.
*
*
* This program is free software; you can redistribute it and/or
......@@ -984,66 +985,6 @@ int udp_rcv(struct sk_buff *skb)
return(0);
}
static void get_udp_sock(struct sock *sp, char *tmpbuf, int i)
{
struct inet_opt *inet = inet_sk(sp);
unsigned int dest, src;
__u16 destp, srcp;
dest = inet->daddr;
src = inet->rcv_saddr;
destp = ntohs(inet->dport);
srcp = ntohs(inet->sport);
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
i, src, srcp, dest, destp, sp->state,
atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
0, 0L, 0,
sock_i_uid(sp), 0,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp);
}
int udp_get_info(char *buffer, char **start, off_t offset, int length)
{
int len = 0, num = 0, i;
off_t pos = 0;
off_t begin;
char tmpbuf[129];
if (offset < 128)
len += sprintf(buffer, "%-127s\n",
" sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout inode");
pos = 128;
read_lock(&udp_hash_lock);
for (i = 0; i < UDP_HTABLE_SIZE; i++) {
struct sock *sk;
for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
if (sk->family != PF_INET)
continue;
pos += 128;
if (pos <= offset)
continue;
get_udp_sock(sk, tmpbuf, i);
len += sprintf(buffer+len, "%-127s\n", tmpbuf);
if(len >= length)
goto out;
}
}
out:
read_unlock(&udp_hash_lock);
begin = len - (pos - offset);
*start = buffer + begin;
len -= begin;
if(len > length)
len = length;
if (len < 0)
len = 0;
return len;
}
struct proto udp_prot = {
.name = "UDP",
.close = udp_close,
......
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