/* * 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 */ #include #include #include #include #include #include #include #include #include #include #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 "); 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 */