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

parent 56338b9f
...@@ -18,6 +18,7 @@ extern void arp_send(int type, int ptype, u32 dest_ip, ...@@ -18,6 +18,7 @@ extern void arp_send(int type, int ptype, u32 dest_ip,
extern int arp_bind_neighbour(struct dst_entry *dst); extern int arp_bind_neighbour(struct dst_entry *dst);
extern int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir); extern int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
extern void arp_ifdown(struct net_device *dev); extern void arp_ifdown(struct net_device *dev);
extern unsigned arp_state_to_flags(struct neighbour *neigh);
extern struct neigh_ops arp_broken_ops; extern struct neigh_ops arp_broken_ops;
......
...@@ -66,6 +66,8 @@ ...@@ -66,6 +66,8 @@
* Alexey Kuznetsov: new arp state machine; * Alexey Kuznetsov: new arp state machine;
* now it is in net/core/neighbour.c. * now it is in net/core/neighbour.c.
* Krzysztof Halasa: Added Frame Relay ARP support. * Krzysztof Halasa: Added Frame Relay ARP support.
* Arnaldo C. Melo : move proc stuff to seq_file and
* net/ipv4/ip_proc.c
*/ */
#include <linux/types.h> #include <linux/types.h>
...@@ -85,7 +87,6 @@ ...@@ -85,7 +87,6 @@
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/trdevice.h> #include <linux/trdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/init.h> #include <linux/init.h>
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
...@@ -851,7 +852,7 @@ int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) ...@@ -851,7 +852,7 @@ int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
} }
/* /*
* User level interface (ioctl, /proc) * User level interface (ioctl)
*/ */
/* /*
...@@ -918,7 +919,7 @@ int arp_req_set(struct arpreq *r, struct net_device * dev) ...@@ -918,7 +919,7 @@ int arp_req_set(struct arpreq *r, struct net_device * dev)
return err; return err;
} }
static unsigned arp_state_to_flags(struct neighbour *neigh) unsigned arp_state_to_flags(struct neighbour *neigh)
{ {
unsigned flags = 0; unsigned flags = 0;
if (neigh->nud_state&NUD_PERMANENT) if (neigh->nud_state&NUD_PERMANENT)
...@@ -1066,111 +1067,6 @@ int arp_ioctl(unsigned int cmd, void *arg) ...@@ -1066,111 +1067,6 @@ int arp_ioctl(unsigned int cmd, void *arg)
return err; return err;
} }
/*
* Write the contents of the ARP cache to a PROCfs file.
*/
#ifndef CONFIG_PROC_FS
static int arp_get_info(char *buffer, char **start, off_t offset, int length)
{
return 0;
}
#else
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
static char *ax2asc2(ax25_address *a, char *buf);
#endif
#define HBUFFERLEN 30
static int arp_get_info(char *buffer, char **start, off_t offset, int length)
{
char hbuffer[HBUFFERLEN];
int i,j,k;
const char hexbuf[] = "0123456789ABCDEF";
int size = sprintf(buffer, "IP address HW type Flags "
"HW address Mask Device\n");
int len = size;
off_t pos = size;
for (i = 0; i <= NEIGH_HASHMASK; i++) {
struct neighbour *n;
read_lock_bh(&arp_tbl.lock);
for (n = arp_tbl.hash_buckets[i]; n; n = n->next) {
char tbuf[16];
struct net_device *dev = n->dev;
int hatype = dev->type;
/* Do not confuse users "arp -a" with magic entries */
if (!(n->nud_state & ~NUD_NOARP))
continue;
read_lock(&n->lock);
/* Convert hardware address to XX:XX:XX:XX ... form. */
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
ax2asc2((ax25_address *)n->ha, hbuffer);
else {
#endif
for (k = 0, j = 0; k < HBUFFERLEN - 3 &&
j < dev->addr_len; j++) {
hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
hbuffer[k++] = hexbuf[n->ha[j] & 15];
hbuffer[k++] = ':';
}
hbuffer[--k] = 0;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
}
#endif
sprintf(tbuf, "%u.%u.%u.%u",
NIPQUAD(*(u32*)n->primary_key));
size = sprintf(buffer + len, "%-16s 0x%-10x0x%-10x%s"
" * %s\n",
tbuf, hatype, arp_state_to_flags(n),
hbuffer, dev->name);
read_unlock(&n->lock);
len += size;
pos += size;
if (pos <= offset)
len = 0;
if (pos >= offset + length) {
read_unlock_bh(&arp_tbl.lock);
goto done;
}
}
read_unlock_bh(&arp_tbl.lock);
}
for (i = 0; i <= PNEIGH_HASHMASK; i++) {
struct pneigh_entry *n;
for (n = arp_tbl.phash_buckets[i]; n; n = n->next) {
struct net_device *dev = n->dev;
int hatype = dev ? dev->type : 0;
char tbuf[16];
sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
size = sprintf(buffer + len, "%-16s 0x%-10x0x%-10x%s"
" * %s\n",
tbuf, hatype, ATF_PUBL | ATF_PERM,
"00:00:00:00:00:00",
dev ? dev->name : "*");
len += size;
pos += size;
if (pos <= offset)
len = 0;
if (pos >= offset+length)
goto done;
}
}
done: *start = buffer + len - (pos - offset); /* Start of wanted data */
len = pos - offset; /* Start slop */
if (len > length)
len = length; /* Ending slop */
if (len < 0)
len = 0;
return len;
}
#endif
/* Note, that it is not on notifier chain. /* Note, that it is not on notifier chain.
It is necessary, that this routine was called after route cache will be It is necessary, that this routine was called after route cache will be
flushed. flushed.
...@@ -1191,54 +1087,13 @@ static struct packet_type arp_packet_type = { ...@@ -1191,54 +1087,13 @@ static struct packet_type arp_packet_type = {
.data = (void*) 1, /* understand shared skbs */ .data = (void*) 1, /* understand shared skbs */
}; };
void __init arp_init (void) void __init arp_init(void)
{ {
neigh_table_init(&arp_tbl); neigh_table_init(&arp_tbl);
dev_add_pack(&arp_packet_type); dev_add_pack(&arp_packet_type);
proc_net_create ("arp", 0, arp_get_info);
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
NET_IPV4_NEIGH, "ipv4"); NET_IPV4_NEIGH, "ipv4");
#endif #endif
} }
#ifdef CONFIG_PROC_FS
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
/*
* ax25 -> ASCII conversion
*/
char *ax2asc2(ax25_address *a, char *buf)
{
char c, *s;
int n;
for (n = 0, s = buf; n < 6; n++) {
c = (a->ax25_call[n] >> 1) & 0x7F;
if (c != ' ') *s++ = c;
}
*s++ = '-';
if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
*s++ = '1';
n -= 10;
}
*s++ = n + '0';
*s++ = '\0';
if (*buf == '\0' || *buf == '-')
return "*";
return buf;
}
#endif
#endif
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/netdevice.h>
#include <net/neighbour.h>
#include <net/arp.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
extern int raw_get_info(char *, char **, off_t, int); extern int raw_get_info(char *, char **, off_t, int);
...@@ -25,8 +29,158 @@ extern int tcp_get_info(char *, char **, off_t, int); ...@@ -25,8 +29,158 @@ extern int tcp_get_info(char *, char **, off_t, int);
extern int udp_get_info(char *, char **, off_t, int); extern int udp_get_info(char *, char **, off_t, int);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#ifdef CONFIG_AX25
/*
* ax25 -> ASCII conversion
*/
char *ax2asc2(ax25_address *a, char *buf)
{
char c, *s;
int n;
for (n = 0, s = buf; n < 6; n++) {
c = (a->ax25_call[n] >> 1) & 0x7F;
if (c != ' ') *s++ = c;
}
*s++ = '-';
if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
*s++ = '1';
n -= 10;
}
*s++ = n + '0';
*s++ = '\0';
if (*buf == '\0' || *buf == '-')
return "*";
return buf;
}
#endif /* CONFIG_AX25 */
static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
{
return (void *)(unsigned long)++*pos;
}
static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
return (void *)(unsigned long)((++*pos) >=
(NEIGH_HASHMASK +
PNEIGH_HASHMASK - 1) ? 0 : *pos);
}
static void arp_seq_stop(struct seq_file *seq, void *v)
{
}
#define HBUFFERLEN 30
static __inline__ void arp_format_neigh_table(struct seq_file *seq, int entry)
{
char hbuffer[HBUFFERLEN];
const char hexbuf[] = "0123456789ABCDEF";
struct neighbour *n;
int k, j;
read_lock_bh(&arp_tbl.lock);
for (n = arp_tbl.hash_buckets[entry]; n; n = n->next) {
char tbuf[16];
struct net_device *dev = n->dev;
int hatype = dev->type;
/* Do not confuse users "arp -a" with magic entries */
if (!(n->nud_state & ~NUD_NOARP))
continue;
read_lock(&n->lock);
/* Convert hardware address to XX:XX:XX:XX ... form. */
#ifdef CONFIG_AX25
if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
ax2asc2((ax25_address *)n->ha, hbuffer);
else {
#endif
for (k = 0, j = 0; k < HBUFFERLEN - 3 &&
j < dev->addr_len; j++) {
hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];
hbuffer[k++] = hexbuf[n->ha[j] & 15];
hbuffer[k++] = ':';
}
hbuffer[--k] = 0;
#ifdef CONFIG_AX25
}
#endif
sprintf(tbuf, "%u.%u.%u.%u",
NIPQUAD(*(u32*)n->primary_key));
seq_printf(seq, "%-16s 0x%-10x0x%-10x%s"
" * %s\n",
tbuf, hatype, arp_state_to_flags(n),
hbuffer, dev->name);
read_unlock(&n->lock);
}
read_unlock_bh(&arp_tbl.lock);
}
static __inline__ void arp_format_pneigh_table(struct seq_file *seq, int entry)
{
struct pneigh_entry *n;
for (n = arp_tbl.phash_buckets[entry]; n; n = n->next) {
struct net_device *dev = n->dev;
int hatype = dev ? dev->type : 0;
char tbuf[16];
sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
seq_printf(seq, "%-16s 0x%-10x0x%-10x%s"
" * %s\n",
tbuf, hatype, ATF_PUBL | ATF_PERM,
"00:00:00:00:00:00",
dev ? dev->name : "*");
}
}
static int arp_seq_show(struct seq_file *seq, void *v)
{
unsigned long l = (unsigned long)v - 1;
if (!l)
seq_puts(seq, "IP address HW type Flags "
"HW address Mask Device\n");
if (l <= NEIGH_HASHMASK)
arp_format_neigh_table(seq, l);
else
arp_format_pneigh_table(seq, l - NEIGH_HASHMASK);
return 0;
}
struct seq_operations arp_seq_ops = {
.start = arp_seq_start,
.next = arp_seq_next,
.stop = arp_seq_stop,
.show = arp_seq_show,
};
static int arp_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &arp_seq_ops);
}
static struct file_operations arp_seq_fops = {
.open = arp_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;
int rc = 0; int rc = 0;
if (!proc_net_create("raw", 0, raw_get_info)) if (!proc_net_create("raw", 0, raw_get_info))
...@@ -46,8 +200,15 @@ int __init ipv4_proc_init(void) ...@@ -46,8 +200,15 @@ int __init ipv4_proc_init(void)
if (!proc_net_create("udp", 0, udp_get_info)) if (!proc_net_create("udp", 0, udp_get_info))
goto out_udp; goto out_udp;
p = create_proc_entry("arp", S_IRUGO, proc_net);
if (!p)
goto out_arp;
p->proc_fops = &arp_seq_fops;
out: out:
return rc; return rc;
out_arp:
proc_net_remove("udp");
out_udp: out_udp:
proc_net_remove("tcp"); proc_net_remove("tcp");
out_tcp: out_tcp:
......
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