lkml.org 
[lkml]   [2003]   [Jan]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subject[RFC] /proc/net/if device/address information module
Hi all,

I asked a couple of weeks ago if there was a way to get the network
interface information from the proc file system for each network
device on the system and recieved little response. After browsing the
code a bit I decided to write a small module which gives acts as a
minimal replacement for the output of ifconfig, since it seemed that
this information should be easy to find in the /proc/net hierarchy but
wasn't available. After writing it for inet (IP) devices, I decided
to add IPV6 and ATalk since it wasn't much more work.

I've included the code attached (it's not very big) since I know that
at least one person wrote me back saying they wanted this feature.
I'm also interested in comments on the code as I've never written any
kernel code before and would like to know what changes would be needed
(if any) before it would be considered for inclusion in the kernel.

Hope someone finds this useful and any comments appreciated.

--
burton samograd
kruhft@kruhft.dyndns.org
http://kruhftwerk.dyndns.org
KERNELDIR=/usr/src/linux-2.4.20-devel
CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -Os -Wall

all: proc_net_if.o

clean:
rm -f *.o *~ core/*
* net/proc_if.c
*
* Adds /proc/net/if/[inet,ipv6,atalk], which contain basic network
* device information for each protocol if supported by the kernel.
* Only tested with inet since that's all I use.
*
* Author: Burton Samograd <kruhft@kruhft.dyndns.org>
*/

#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/ipv6.h>
#include <net/if_inet6.h>
#include <linux/atalk.h>
#include <linux/string.h>

#ifdef CONFIG_NET
#ifdef CONFIG_PROC_FS

struct proc_dir_entry *proc_net_if;
static int proc_net_if_init(void);
static void proc_net_if_cleanup(void);

#ifdef CONFIG_IPV6
static struct proc_dir_entry *proc_net_if_ipv6;
static int proc_net_if_ipv6_info(char *page, char**start, off_t off, int count)
{
int len = 0;
struct net_device *device = dev_base;

_raw_read_lock(&dev_base_lock);
MOD_INC_USE_COUNT;

len += sprintf(page+len, "iface\taddr\n");
while(device) {
struct inet6_dev *iface =
(struct inet6_dev*)device->ip6_ptr;
while(iface) {
struct inet6_ifaddr *addrlst = iface->addr_list;
while(addrlst) {
struct in6_addr *addr = &addrlst->addr;
/* correct? i'm not too familiar with ipv6 */
len += printk(page+len, "%s\t%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",
device->name,
addr->s6_addr[0], addr->s6_addr[1],
addr->s6_addr[2], addr->s6_addr[3],
addr->s6_addr[4], addr->s6_addr[5],
addr->s6_addr[6], addr->s6_addr[7],
addr->s6_addr[8], addr->s6_addr[9],
addr->s6_addr[10], addr->s6_addr[11],
addr->s6_addr[12], addr->s6_addr[13],
addr->s6_addr[14], addr->s6_addr[15]
);
addrlst = addrlst->if_next;
}
iface = iface->next;
}
device = device->next;
}

_raw_read_unlock(&dev_base_lock);
MOD_DEC_USE_COUNT;
return len;
}
#endif /* CONFIG_IPV6 */

#ifdef CONFIG_INET
static struct proc_dir_entry *proc_net_if_inet;
static int proc_net_if_inet_info(char *page, char**start, off_t off, int count)
{
int len = 0;
struct net_device *device = dev_base;

_raw_read_lock(&dev_base_lock);
MOD_INC_USE_COUNT;

len += sprintf(page+len, "iface\taddr\t\tbcast\t\tmask\n");
while(device) {
if(device->ip_ptr) {
struct in_ifaddr *iface =
((struct in_device*)device->ip_ptr)->ifa_list;
while(iface) {
len += sprintf(page+len,
"%s\t%8.8x\t%8.8x\t%8.8x\n",
iface->ifa_label, iface->ifa_address,
iface->ifa_broadcast, iface->ifa_mask);
iface = iface->ifa_next;
}
}
device = device->next;
}

_raw_read_unlock(&dev_base_lock);
MOD_DEC_USE_COUNT;
return len;
}
#endif /* CONFIG_INET */

#ifdef CONFIG_ATALK
static struct proc_dir_entry *proc_net_if_atalk;
static int proc_net_if_atalk_info(char *page, char**start, off_t off, int count)
{
int len = 0;
struct net_device *device = dev_base;

_raw_read_lock(&dev_base_lock);
MOD_INC_USE_COUNT;

len += sprintf(page+len, "name\tnet\tnode\n");
while(device) {
/* only ip device for now */
if(device->atalk_ptr) {
struct atalk_iface *iface = atalk_find_dev(device);
while(iface) {
struct at_addr* addr = atalk_find_dev_addr(device);
if(addr) {
len += sprintf(page+len,
"%s\t%8.8x\t%8.8x\n",
iface->dev->name, addr->s_net, addr->s_node);
}
iface = iface->next;
}
}
device = device->next;
}

_raw_read_unlock(&dev_base_lock);
MOD_DEC_USE_COUNT;
return len;
}
#endif /* CONFIG_ATALK */

static int proc_net_if_init(void)
{
if(dev_base == NULL)
return -1;

proc_net_if = proc_mkdir("if", proc_net);
if(!proc_net_if) {
proc_net_if_cleanup();
return -1;
}
proc_net_if->owner = THIS_MODULE;

#ifdef CONFIG_INET
proc_net_if_inet = create_proc_info_entry("inet", (mode_t)0444,
proc_net_if,
proc_net_if_inet_info);
if(proc_net_if_inet == NULL) {
proc_net_if_cleanup();
return -1;
}
proc_net_if_inet->owner = THIS_MODULE;
#endif /* CONFIG_INET */

#ifdef CONFIG_IPV6
proc_net_if_ipv6 = create_proc_info_entry("ipv6", (mode_t)0444,
proc_net_if,
proc_net_if_ipv6_info);
if(proc_net_if_ipv6 == NULL) {
proc_net_if_cleanup();
return -1;
}
proc_net_if_ipv6->owner = THIS_MODULE;
#endif /* CONFIG_IPV6 */

#ifdef CONFIG_ATALK
proc_net_if_atalk = create_proc_info_entry("atalk", (mode_t)0444,
proc_net_if,
proc_net_if_atalk_info);
if(proc_net_if_atalk == NULL) {
proc_net_if_cleanup();
return -1;
}
proc_net_if_atalk->owner = THIS_MODULE;
#endif /* CONFIG_ATALK */

return 0;
}

static void proc_net_if_cleanup(void)
{
#ifdef CONFIG_INET
if(proc_net_if_inet)
remove_proc_entry("inet", proc_net_if_inet);
#endif /* CONFIG_INET */
#ifdef CONFIG_IPV6
if(proc_net_if_ipv6)
remove_proc_entry("ipv6", proc_net_if_ipv6);
#endif /* CONFIG_IPV6 */
#ifdef CONFIG_ATALK
if(proc_net_if_atalk)
remove_proc_entry("atalk", proc_net_if_atalk);
#endif /* CONFIG_ATALK */
if(proc_net_if)
remove_proc_entry("if", proc_net);

return;
}

#ifdef CONFIG_MODULES
module_init(proc_net_if_init);
module_exit(proc_net_if_cleanup);

MODULE_AUTHOR("Burton Samograd <kruhft@kruhft.dyndns.org>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IPv4 network information listing system network devices");
EXPORT_NO_SYMBOLS;
#endif /* CONFIG_MODULES */

#endif /* CONFIG_PROC_FS */
#endif /* CONFIG_NET */
[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2005-03-22 13:32    [W:0.225 / U:0.372 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site