wanpipe/patches/kdrivers/src/wanrouter/wanproc.c

2189 lines
55 KiB
C

/*****************************************************************************
* wanproc.c WAN Router Module. /proc filesystem interface.
*
* This module is completely hardware-independent and provides
* access to the router using Linux /proc filesystem.
*
* Author: Gideon Hack
* Nenad Corbic
*
* Copyright: (c) 1995-2004 Sangoma Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
* Aug 20, 2001 Alex Feldman Support SNMP.
* May 25, 2001 Alex Feldman Added T1/E1 support (TE1).
* May 23, 2001 Nenad Corbic Bug fix supplied by Akash Jain. If the user
* copy fails free up allocated memory.
* Jun 02, 1999 Gideon Hack Updates for Linux 2.2.X kernels.
* Jun 29, 1997 Alan Cox Merged with 1.0.3 vendor code
* Jan 29, 1997 Gene Kozin v1.0.1. Implemented /proc read routines
* Jan 30, 1997 Alan Cox Hacked around for 2.1
* Dec 13, 1996 Gene Kozin Initial version (based on Sangoma's WANPIPE)
*****************************************************************************/
#include "wanpipe_includes.h"
#include "wanpipe_version.h"
#include "wanpipe_defines.h"
#include "wanpipe_debug.h"
#include "wanpipe_common.h"
#include "wanpipe.h"
#include "sdladrv.h"
#include "wanproc.h"
#include "if_wanpipe_common.h"
#if !defined(__WINDOWS__)
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
# define STATIC
# define CONFIG_PROC_FS
#else
# define STATIC static
#endif
#if defined(__LINUX__)
# if defined(LINUX_2_1) || defined(LINUX_2_4)
# ifndef proc_mkdir
# define proc_mkdir(buf, usbdir) create_proc_entry(buf, S_IFDIR, usbdir)
# endif
# endif
# if defined(LINUX_2_6)
# define M_STOP_CNT(m) NULL
# else
# define M_STOP_CNT(m) &m->stop_cnt
# endif
#endif
#define PROC_STATS_1_FORMAT "%25s: %10lu\n"
#define PROC_STATS_2_FORMAT "%25s: %10lu %25s: %10lu\n"
#define PROC_STATS_ALARM_FORMAT "%25s: %10s %25s: %10s\n"
#define PROC_STATS_STR_FORMAT "%25s: %10s\n"
/****** Defines and Macros **************************************************/
#ifndef wp_min
#define wp_min(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef wp_max
#define wp_max(a,b) (((a)>(b))?(a):(b))
#endif
#define PROC_BUFSZ 4000 /* buffer size for printing proc info */
#define PROT_UNKNOWN "Unknown"
#define PROT_DECODE(prot,cap) ((prot == WANCONFIG_FR) ? ((cap)?"FR":"fr") :\
(prot == WANCONFIG_MFR) ? ((cap)?"FR":"fr") : \
(prot == WANCONFIG_X25) ? ((cap)?"X25":"x25") : \
(prot == WANCONFIG_PPP) ? ((cap)?"PPP":"ppp") : \
(prot == WANCONFIG_CHDLC) ? ((cap)?"CHDLC":"chdlc") :\
(prot == WANCONFIG_ADSL) ? ((cap)?"ADSL":"adsl") :\
(prot == WANCONFIG_MPPP) ? ((cap)?"S51X":"s51x") : \
(prot == WANCONFIG_SDLC) ? ((cap)?"SDLC":"sdlc") : \
(prot == WANCONFIG_ATM) ? ((cap)?"ATM":"atm") : \
(prot == WANCONFIG_AFT) ? ((cap)?"AFT TE1":"aft te1") : \
(prot == WANCONFIG_AFT_T116) ? ((cap)?"AFT TE1":"aft te1") : \
(prot == WANCONFIG_AFT_SERIAL) ? ((cap)?"A-SERIAL":"aft serial") : \
(prot == WANCONFIG_AFT_ANALOG) ? ((cap)?"A-ANALOG":"aft analog") : \
(prot == WANCONFIG_AFT_GSM) ? ((cap)?"AFT GSM":"aft gsm") : \
(prot == WANCONFIG_AFT_ISDN_BRI) ? ((cap)?"AFT ISDN":"aft isdn") : \
(prot == WANCONFIG_AFT_56K) ? ((cap)?"AFT 56K":"aft 56k") : \
(prot == WANCONFIG_AFT_TE1) ? ((cap)?"AFT TE1":"aft te1") : \
(prot == WANCONFIG_AFT_TE3) ? ((cap)?"AFT TE3":"aft te3") : \
PROT_UNKNOWN )
#define CARD_DECODE(wandev) ((wandev->card_type == WANOPT_ADSL) ? "ADSL" : \
(wandev->card_type == WANOPT_S50X) ? "S508" : \
(wandev->card_type == WANOPT_AFT) ? "AFT TE1" : \
(wandev->card_type == WANOPT_AFT_101) ? "A101" : \
(wandev->card_type == WANOPT_AFT_102) ? "A102" : \
(wandev->card_type == WANOPT_AFT_104) ? "A104" : \
(wandev->card_type == WANOPT_AFT_108) ? "A108" : \
(wandev->card_type == WANOPT_AFT_300) ? "A301" : \
(wandev->card_type == WANOPT_AFT_300) ? "A301" : \
(wandev->card_type == WANOPT_AFT_ANALOG) ? "A200/A400" : \
(wandev->card_type == WANOPT_AFT_ISDN) ? "A500" : \
(wandev->card_type == WANOPT_AFT_SERIAL) ? "A14X" : \
(wandev->fe_iface.get_fe_media_string) ? \
wandev->fe_iface.get_fe_media_string() : "S514")
/****** Data Types **********************************************************/
#if defined(__LINUX__)
typedef struct wan_stat_entry
{
struct wan_stat_entry *next;
char *description; /* description string */
void *data; /* -> data */
unsigned data_type; /* data type */
} wan_stat_entry_t;
typedef struct wan_proc_entry
{
struct proc_dir_entry *protocol_entry;
int count;
} wan_proc_entry_t;
#endif
/****** Function Prototypes *************************************************/
extern wan_spinlock_t wan_devlist_lock;
extern struct wan_devlist_ wan_devlist;
#if defined(CONFIG_PROC_FS)
#define CONF_PCI_FRM "%-12s| %-13s| %-9s| %-4u| %-8u| %-5u| %-4s| %-10u|\n"
#define CONF_ISA_FRM "%-12s| %-13s| %-9s| %-4u| 0x%-6X| %-5u| %-4s| %-10u|\n"
#define MAP_FRM "%-12s| %-50s\n"
#define INTERFACES_FRM "%-15s| %-12s| %-6u| %-18s|\n"
#define PROC_FR_FRM "%-30s\n"
#define PROC_FR_CFG_FRM "%-15s| %-12s| %-5u|\n"
#define PROC_FR_STAT_FRM "%-15s| %-12s| %-14s|\n"
#ifdef CONFIG_PRODUCT_WANPIPE_ANNEXG
#define STAT_FRM "%-12s| %-9s| %-8s| %-14s| %-3u | %-3u | %-3u | %-3u | %-3u | %-3u | %-3u | %-3u | %-3u | %-3u |\n"
#else
#define STAT_FRM "%-12s| %-9s| %-8s| %-14s|\n"
#endif
/* NEW_PROC */
/* Strings */
static char conf_hdr[] =
"Device name | Protocol Map | Adapter | IRQ | Slot/IO "
"| If's | CLK | Baud rate |\n";
#if defined(__LINUX__)
static char map_hdr[] =
"Device name | Protocol Map \n";
#endif
#ifdef CONFIG_PRODUCT_WANPIPE_ANNEXG
static char stat_hdr[] =
"Device name | Protocol | Station | Status | Wanpipe | Lapb | X25 Link | X25 Svc | Dsp |\n";
#else
static char stat_hdr[] =
"Device name | Protocol | Station | Status |\n";
#endif
static char interfaces_hdr[] =
"Interface name | Device name | Media | Operational State |\n";
#if defined(__LINUX__)
/* Proc filesystem interface */
#ifndef LINUX_2_6
static int router_proc_perms(struct inode *, int);
static ssize_t router_proc_read(struct file*, char*, size_t,loff_t*);
static ssize_t router_proc_write(struct file*, const char*, size_t,loff_t*);
#endif
/* Methods for preparing data for reading proc entries */
#if defined(LINUX_2_6)
static int config_get_info(struct seq_file *m, void *v);
static int status_get_info(struct seq_file *m, void *v);
static int probe_get_info(struct seq_file *m, void *v);
static int probe_get_info_legacy(struct seq_file *m, void *v);
static int probe_get_info_verbose(struct seq_file *m, void *v);
static int probe_get_info_dump(struct seq_file *m, void *v);
static int wandev_get_info(struct seq_file *m, void *v);
static int map_get_info(struct seq_file *m, void *v);
static int interfaces_get_info(struct seq_file *m, void *v);
static int get_dev_config_info(struct seq_file *m, void *v);
static int get_dev_status_info(struct seq_file *m, void *v);
static int wandev_mapdir_get_info(struct seq_file *m, void *v);
#elif defined(LINUX_2_4)
static int config_get_info(char* buf, char** start, off_t offs, int len);
static int status_get_info(char* buf, char** start, off_t offs, int len);
static int probe_get_info(char* buf, char** start, off_t offs, int len);
static int probe_get_info_legacy(char* buf, char** start, off_t offs, int len);
static int probe_get_info_verbose(char* buf, char** start, off_t offs, int len);
static int probe_get_info_dump(char* buf, char** start, off_t offs, int len);
static int wandev_get_info(char* buf, char** start, off_t offs, int len);
static int map_get_info(char* buf, char** start, off_t offs, int len);
static int interfaces_get_info(char* buf, char** start, off_t offs, int len);
static int get_dev_config_info(char* buf, char** start, off_t offs, int len);
static int get_dev_status_info(char* buf, char** start, off_t offs, int len);
static int wandev_mapdir_get_info(char* buf, char** start, off_t offs, int len);
#else
static int config_get_info(char* buf, char** start, off_t offs, int len, int dummy);
static int status_get_info(char* buf, char** start, off_t offs, int len, int dummy);
static int probe_get_info(char* buf, char** start, off_t offs, int len, int dummy);
static int probe_get_info_legacy(char* buf, char** start, off_t offs, int len, int dummy);
static int probe_get_info_verbose(char* buf, char** start, off_t offs, int len, int dummy);
static int probe_get_info_dump(char* buf, char** start, off_t offs, int len, int dummy);
static int wandev_get_info(char* buf, char** start, off_t offs, int len, int dummy);
static int map_get_info(char* buf, char** start, off_t offs, int len, int dummy);
static int interfaces_get_info(char* buf, char** start, off_t offs, int len, int dummy);
static int get_dev_config_info(char* buf, char** start, off_t offs, int len, int dummy);
static int get_dev_status_info(char* buf, char** start, off_t offs, int len, int dummy);
#endif
/* Miscellaneous */
/*
* Structures for interfacing with the /proc filesystem.
* Router creates its own directory /proc/net/wanrouter with the folowing
* entries:
* config device configuration
* status global device statistics
* <device> entry for each WAN device
*/
/*
* Generic /proc/net/wanrouter/<file> file and inode operations
*/
struct proc_dir_entry *proc_router;
static struct proc_dir_entry *map_dir;
#ifdef LINUX_2_6
static int config_open(struct inode *inode, struct file *file)
{
return single_open(file, config_get_info, WP_PDE_DATA(inode));
}
static int status_open(struct inode *inode, struct file *file)
{
return single_open(file, status_get_info, WP_PDE_DATA(inode));
}
static struct file_operations config_fops = {
.owner = THIS_MODULE,
.open = config_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static struct file_operations status_fops = {
.owner = THIS_MODULE,
.open = status_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wandev_open(struct inode *inode, struct file *file)
{
return single_open(file, wandev_get_info, WP_PDE_DATA(inode));
}
static struct file_operations wandev_fops = {
.owner = THIS_MODULE,
.open = wandev_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.WAN_IOCTL = wanrouter_ioctl,
};
static int wp_hwprobe_open(struct inode *inode, struct file *file)
{
return single_open(file, probe_get_info, WP_PDE_DATA(inode));
}
static struct file_operations wp_hwprobe_fops = {
.owner = THIS_MODULE,
.open = wp_hwprobe_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_hwprobe_legacy_open(struct inode *inode, struct file *file)
{
return single_open(file, probe_get_info_legacy, WP_PDE_DATA(inode));
}
static struct file_operations wp_hwprobe_legacy_fops = {
.owner = THIS_MODULE,
.open = wp_hwprobe_legacy_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_hwprobe_verbose_open(struct inode *inode, struct file *file)
{
return single_open(file, probe_get_info_verbose, WP_PDE_DATA(inode));
}
static struct file_operations wp_hwprobe_verbose_fops = {
.owner = THIS_MODULE,
.open = wp_hwprobe_verbose_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_hwprobe_dump_open(struct inode *inode, struct file *file)
{
return single_open(file, probe_get_info_dump, WP_PDE_DATA(inode));
}
static struct file_operations wp_hwprobe_dump_fops = {
.owner = THIS_MODULE,
.open = wp_hwprobe_dump_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_map_open(struct inode *inode, struct file *file)
{
return single_open(file, map_get_info, WP_PDE_DATA(inode));
}
static struct file_operations wp_map_fops = {
.owner = THIS_MODULE,
.open = wp_map_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_iface_open(struct inode *inode, struct file *file)
{
return single_open(file, interfaces_get_info, WP_PDE_DATA(inode));
}
static struct file_operations wp_iface_fops = {
.owner = THIS_MODULE,
.open = wp_iface_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wandev_mapdir_open(struct inode *inode, struct file *file)
{
return single_open(file, wandev_mapdir_get_info, WP_PDE_DATA(inode));
}
static struct file_operations wandev_mapdir_fops = {
.owner = THIS_MODULE,
.open = wandev_mapdir_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_get_dev_config_open(struct inode *inode, struct file *file)
{
return single_open(file, get_dev_config_info, WP_PDE_DATA(inode));
}
static struct file_operations wp_get_dev_config_fops = {
.owner = THIS_MODULE,
.open = wp_get_dev_config_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int wp_get_dev_status_open(struct inode *inode, struct file *file)
{
return single_open(file, get_dev_status_info, WP_PDE_DATA(inode));
}
static struct file_operations wp_get_dev_status_fops = {
.owner = THIS_MODULE,
.open = wp_get_dev_status_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#if 0
static int wp_prot_dev_config_open(struct inode *inode, struct file *file)
{
return 0;
//return single_open(file, get_dev_status_info, WP_PDE_DATA(inode));
}
static struct file_operations wp_prot_dev_config_fops = {
.owner = THIS_MODULE,
.open = wp_prot_dev_config_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
#elif defined(LINUX_2_4)
static struct file_operations router_fops =
{
read: router_proc_read,
write: router_proc_write,
};
static struct inode_operations router_inode =
{
permission: router_proc_perms,
};
/*
* /proc/net/wanrouter/<device> file operations
*/
static struct file_operations wandev_fops =
{
read: router_proc_read,
WAN_IOCTL: wanrouter_ioctl,
};
/*
* /proc/net/wanrouter
*/
#else
static struct file_operations router_fops =
{
NULL, /* lseek */
router_proc_read, /* read */
router_proc_write, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* flush */
NULL, /* no special release code */
NULL /* can't fsync */
};
static struct inode_operations router_inode =
{
&router_fops,
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* follow link */
NULL, /* readlink */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
router_proc_perms
};
static struct file_operations wandev_fops =
{
NULL, /* lseek */
router_proc_read, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
wanrouter_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* flush */
NULL, /* no special release code */
NULL /* can't fsync */
};
static struct inode_operations wandev_inode =
{
&wandev_fops,
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
router_proc_perms
};
#endif
/*
* /proc/net/wanrouter/<protocol>
*/
wan_proc_entry_t proc_router_fr;
wan_proc_entry_t proc_router_chdlc;
wan_proc_entry_t proc_router_ppp;
wan_proc_entry_t proc_router_x25;
#endif /* __LINUX__ */
/*
* Interface functions
*/
/*
* Prepare data for reading 'Config' entry.
* Return length of data.
*/
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int config_get_info(char* buf, char** start, off_t offs, int len)
#else
#if defined(LINUX_2_6)
static int config_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int config_get_info(char* buf, char** start, off_t offs, int len)
#else
static int config_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
#endif
{
wan_device_t* wandev = NULL;
wan_smp_flag_t flags;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "%s", conf_hdr);
wan_spin_lock(&wan_devlist_lock,&flags);
WAN_LIST_FOREACH(wandev, &wan_devlist, next){
/*for (wandev = router_devlist; wandev; wandev = wandev->next){*/
sdla_t* card = (sdla_t*)wandev->priv;
u16 arg = 0;
if (!wandev->state) continue;
if (card && card->hw_iface.getcfg){
card->hw_iface.getcfg(card->hw,
(wandev->card_type==WANOPT_S50X) ?
SDLA_IOPORT : SDLA_SLOT,
&arg);
}
if (wandev->state){
PROC_ADD_LINE(m ,
(wandev->card_type==WANOPT_S50X)?CONF_ISA_FRM:CONF_PCI_FRM,
wandev->name,
"N/A", /* FIXME */
SDLA_DECODE_CARDTYPE(wandev->card_type),
wandev->irq,
arg,
wandev->ndev,
(wandev->card_type==WANOPT_S51X || wandev->card_type==WANOPT_AFT_SERIAL) ? CLK_DECODE(wandev->clocking) : "N/A",
wandev->bps);
}
}
wan_spin_unlock(&wan_devlist_lock,&flags);
PROC_ADD_RET(m);
}
/*
* Prepare data for reading 'Status' entry.
* Return length of data.
*/
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int status_get_info(char* buf, char** start, off_t offs, int len)
#else
#if defined(LINUX_2_6)
static int status_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int status_get_info(char* buf, char** start, off_t offs, int len)
#else
static int status_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
#endif
{
struct wan_dev_le *devle;
wan_device_t* wandev = NULL;
wan_smp_flag_t flags;
#ifdef CONFIG_PRODUCT_WANPIPE_ANNEXG
netdevice_t *dev;
wp_stack_stats_t wp_stats;
#endif
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "%s", stat_hdr);
devle=NULL;
wan_spin_lock(&wan_devlist_lock,&flags);
WAN_LIST_FOREACH(wandev, &wan_devlist, next){
if (!wandev->state) continue;
#ifdef CONFIG_PRODUCT_WANPIPE_ANNEXG
memset(&wp_stats,0,sizeof(wp_stack_stats_t));
if (wandev->get_active_inactive){
wan_spin_lock(&wandev->dev_head_lock,&flags);
WAN_LIST_FOREACH(devle, &wandev->dev_head, dev_link){
dev = WAN_DEVLE2DEV(devle);
if (!dev || !(dev->flags&IFF_UP) || !wan_netif_priv(dev)){
continue;
}
wandev->get_active_inactive(wandev,dev,&wp_stats);
}
wan_spin_unlock(&wandev->dev_head_lock,&flags);
}
PROC_ADD_LINE(m,
STAT_FRM,
wandev->name,
PROT_DECODE(wandev->config_id,1),
wandev->config_id == WANCONFIG_FR ?
FR_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_MFR ?
FR_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_ADSL ?
ADSL_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_X25 ?
X25_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_AFT ?
"A1/2 TE1":
wandev->config_id == WANCONFIG_AFT_TE1 ?
"A104 TE1":
wandev->config_id == WANCONFIG_AFT_TE3 ?
"A300 TE3" :
wandev->config_id == WANCONFIG_AFT_ANALOG ?
"A200 RM" :
("N/A"),
STATE_DECODE(wandev->state),
wp_stats.fr_active,wp_stats.fr_inactive,
wp_stats.lapb_active,wp_stats.lapb_inactive,
wp_stats.x25_link_active,wp_stats.x25_link_inactive,
wp_stats.x25_active,wp_stats.x25_inactive,
wp_stats.dsp_active,wp_stats.dsp_inactive);
#else
PROC_ADD_LINE(m,
STAT_FRM,
wandev->name,
PROT_DECODE(wandev->config_id,1),
wandev->config_id == WANCONFIG_FR ?
FR_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_MFR ?
FR_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_ADSL ?
ADSL_STATION_DECODE(wandev->station) :
wandev->config_id == WANCONFIG_X25 ?
X25_STATION_DECODE(wandev->station) :
("N/A"),
STATE_DECODE(wandev->state));
#endif
}
wan_spin_unlock(&wan_devlist_lock,&flags);
PROC_ADD_RET(m);
}
/*
* Prepare data for reading 'Interfaces' entry.
* Return length of data.
*/
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int interfaces_get_info(char* buf, char** start, off_t offs, int len)
#else
#if defined(LINUX_2_6)
static int interfaces_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int interfaces_get_info(char* buf, char** start, off_t offs, int len)
#else
static int interfaces_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
#endif
{
struct wan_dev_le *devle;
wan_device_t* wandev = NULL;
netdevice_t* dev=NULL;
wan_smp_flag_t flags;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "%s", interfaces_hdr);
wan_spin_lock(&wan_devlist_lock,&flags);
WAN_LIST_FOREACH(wandev, &wan_devlist, next){
wanpipe_common_t *dev_priv;
if (!(m->count < (m->size - 80))) break;
if (!wandev->state) continue;
wan_spin_lock(&wandev->dev_head_lock,&flags);
WAN_LIST_FOREACH(devle, &wandev->dev_head, dev_link){
dev = WAN_DEVLE2DEV(devle);
if (!dev || !WAN_NETIF_UP(dev) || !wan_netif_priv(dev)){
continue;
}
dev_priv = wan_netif_priv(dev);
PROC_ADD_LINE(m,
INTERFACES_FRM,
wan_netif_name(dev), wandev->name,
dev_priv->lcn,
dev_priv?STATE_DECODE(dev_priv->state):"N/A");
if (dev_priv->usedby == STACK){
wanpipe_lip_get_if_status(dev_priv,m);
}
}
wan_spin_unlock(&wandev->dev_head_lock,&flags);
}
wan_spin_unlock(&wan_devlist_lock,&flags);
PROC_ADD_RET(m);
}
#define SANGOMA_COUNT_MESSAGE "\nSangoma Card Count: "
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int probe_get_info(char* buf, char** start, off_t offs, int len)
#else
#if defined(LINUX_2_6)
static int probe_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int probe_get_info(char* buf, char** start, off_t offs, int len)
#else
static int probe_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
#endif
{
int i=0;
sdla_hw_probe_t* hw_probe;
sdla_hw_type_cnt_t *hw_cnt;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "-------------------------------\n");
PROC_ADD_LINE(m, "| Wanpipe Hardware Probe Info |\n");
PROC_ADD_LINE(m, "-------------------------------\n");
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
if (hw_probe->index) {
if (hw_probe->index > i) {
i=hw_probe->index;
}
PROC_ADD_LINE(m,
"%-2d. %s\n", hw_probe->index, hw_probe->hw_info);
}
}
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
if (!hw_probe->index) {
i++;
PROC_ADD_LINE(m,
"%-2d. %s\n", i, hw_probe->hw_info);
}
}
hw_cnt=(sdla_hw_type_cnt_t*)sdla_get_hw_adptr_cnt();
PROC_ADD_LINE(m, SANGOMA_COUNT_MESSAGE);
if (hw_cnt->s508_adapters){
PROC_ADD_LINE(m, "S508=%d ", hw_cnt->s508_adapters);
}
if (hw_cnt->s514x_adapters){
PROC_ADD_LINE(m, "S514X=%d ", hw_cnt->s514x_adapters);
}
if (hw_cnt->s518_adapters){
PROC_ADD_LINE(m, "S518=%d ", hw_cnt->s518_adapters);
}
if (hw_cnt->aft101_adapters){
PROC_ADD_LINE(m, "A101-2=%d ", hw_cnt->aft101_adapters);
}
if (hw_cnt->aft104_adapters){
PROC_ADD_LINE(m, "A104=%d ", hw_cnt->aft104_adapters);
}
if (hw_cnt->aft108_adapters){
PROC_ADD_LINE(m, "A108=%d ", hw_cnt->aft108_adapters);
}
if (hw_cnt->aft200_adapters){
PROC_ADD_LINE(m, "A200=%d ", hw_cnt->aft200_adapters);
}
if (hw_cnt->aft_56k_adapters){
PROC_ADD_LINE(m, "A056=%d ", hw_cnt->aft_56k_adapters);
}
if (hw_cnt->aft_isdn_adapters){
PROC_ADD_LINE(m, "A500=%d ", hw_cnt->aft_isdn_adapters);
}
if (hw_cnt->aft_b500_adapters){
PROC_ADD_LINE(m, "B500=%d ", hw_cnt->aft_b500_adapters);
}
if (hw_cnt->aft_a700_adapters){
PROC_ADD_LINE(m, "B700=%d ", hw_cnt->aft_a700_adapters);
}
if (hw_cnt->aft_serial_adapters){
PROC_ADD_LINE(m, "A14x=%d ", hw_cnt->aft_serial_adapters);
}
if (hw_cnt->aft300_adapters){
PROC_ADD_LINE(m, "A300=%d ", hw_cnt->aft300_adapters);
}
if (hw_cnt->usb_adapters){
PROC_ADD_LINE(m, "U100=%d ", hw_cnt->usb_adapters);
}
if (hw_cnt->aft_a600_adapters){
PROC_ADD_LINE(m, "B600=%d ", hw_cnt->aft_a600_adapters);
}
if (hw_cnt->aft_b601_adapters){
PROC_ADD_LINE(m, "B601=%d ", hw_cnt->aft_b601_adapters);
}
if (hw_cnt->aft_b610_adapters){
PROC_ADD_LINE(m, "B610=%d ", hw_cnt->aft_b610_adapters);
}
if (hw_cnt->aft_b800_adapters){
PROC_ADD_LINE(m, "B800=%d ", hw_cnt->aft_b800_adapters);
}
if (hw_cnt->aft_w400_adapters){
PROC_ADD_LINE(m, "W400=%d ", hw_cnt->aft_w400_adapters);
}
if (hw_cnt->aft116_adapters){
PROC_ADD_LINE(m, "A116=%d ", hw_cnt->aft116_adapters);
}
if (hw_cnt->aft_t116_adapters){
PROC_ADD_LINE(m, "T116=%d ", hw_cnt->aft_t116_adapters);
}
PROC_ADD_LINE(m, "\n");
PROC_ADD_RET(m);
}
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int probe_get_info_legacy(char* buf, char** start, off_t offs, int len)
#else
#if defined(LINUX_2_6)
static int probe_get_info_legacy(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int probe_get_info_legacy(char* buf, char** start, off_t offs, int len)
#else
static int probe_get_info_legacy(char* buf, char** start, off_t offs, int len, int dummy)
#endif
#endif
{
int i=0;
sdla_hw_probe_t* hw_probe;
sdla_hw_type_cnt_t *hw_cnt;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "----------------------------------------\n");
PROC_ADD_LINE(m, "| Wanpipe Hardware Probe Info (Legacy) |\n");
PROC_ADD_LINE(m, "----------------------------------------\n");
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
i++;
PROC_ADD_LINE(m,
"%-2d. %s\n", i, hw_probe->hw_info);
}
hw_cnt=(sdla_hw_type_cnt_t*)sdla_get_hw_adptr_cnt();
PROC_ADD_LINE(m,
"\nCard Cnt: S508=%d S514X=%d S518=%d A101-2=%d A104=%d A300=%d A200=%d A108=%d A056=%d\n A500=%d A14x=%d A600=%d B601=%d A116=%d\n",
hw_cnt->s508_adapters,
hw_cnt->s514x_adapters,
hw_cnt->s518_adapters,
hw_cnt->aft101_adapters,
hw_cnt->aft104_adapters,
hw_cnt->aft300_adapters,
hw_cnt->aft200_adapters,
hw_cnt->aft108_adapters,
hw_cnt->aft_56k_adapters,
hw_cnt->aft_isdn_adapters,
hw_cnt->aft_serial_adapters,
hw_cnt->aft_a600_adapters,
hw_cnt->aft_b601_adapters,
hw_cnt->aft116_adapters
);
PROC_ADD_RET(m);
}
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int probe_get_info_verbose(char* buf, char** start, off_t offs, int len)
#else
# if defined(LINUX_2_6)
static int probe_get_info_verbose(struct seq_file *m, void *v)
# elif defined(LINUX_2_4)
static int probe_get_info_verbose(char* buf, char** start, off_t offs, int len)
# else
static int probe_get_info_verbose(char* buf, char** start, off_t offs, int len, int dummy)
# endif
#endif
{
int i=0;
sdla_hw_probe_t* hw_probe;
sdla_hw_type_cnt_t *hw_cnt;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "-----------------------------------------\n");
PROC_ADD_LINE(m, "| Wanpipe Hardware Probe Info (verbose) |\n");
PROC_ADD_LINE(m, "-----------------------------------------\n");
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
if (hw_probe->index) {
if (hw_probe->index > i) {
i=hw_probe->index;
}
PROC_ADD_LINE(m,
"%-2d. %s", hw_probe->index, hw_probe->hw_info);
PROC_ADD_LINE(m,
"%s\n", hw_probe->hw_info_verbose);
}
}
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
if (!hw_probe->index) {
i++;
PROC_ADD_LINE(m,
"%-2d. %s", i, hw_probe->hw_info);
PROC_ADD_LINE(m,
"%s\n", hw_probe->hw_info_verbose);
}
}
hw_cnt=(sdla_hw_type_cnt_t*)sdla_get_hw_adptr_cnt();
PROC_ADD_LINE(m, SANGOMA_COUNT_MESSAGE);
if (hw_cnt->s508_adapters){
PROC_ADD_LINE(m, "S508=%d ", hw_cnt->s508_adapters);
}
if (hw_cnt->s514x_adapters){
PROC_ADD_LINE(m, "S514X=%d ", hw_cnt->s514x_adapters);
}
if (hw_cnt->s518_adapters){
PROC_ADD_LINE(m, "S518=%d ", hw_cnt->s518_adapters);
}
if (hw_cnt->aft101_adapters){
PROC_ADD_LINE(m, "A101-2=%d ", hw_cnt->aft101_adapters);
}
if (hw_cnt->aft104_adapters){
PROC_ADD_LINE(m, "A104=%d ", hw_cnt->aft104_adapters);
}
if (hw_cnt->aft108_adapters){
PROC_ADD_LINE(m, "A108=%d ", hw_cnt->aft108_adapters);
}
if (hw_cnt->aft200_adapters){
PROC_ADD_LINE(m, "A200=%d ", hw_cnt->aft200_adapters);
}
if (hw_cnt->aft_56k_adapters){
PROC_ADD_LINE(m, "A056=%d ", hw_cnt->aft_56k_adapters);
}
if (hw_cnt->aft_isdn_adapters){
PROC_ADD_LINE(m, "A500=%d ", hw_cnt->aft_isdn_adapters);
}
if (hw_cnt->aft_a700_adapters){
PROC_ADD_LINE(m, "B700=%d ", hw_cnt->aft_a700_adapters);
}
if (hw_cnt->aft_serial_adapters){
PROC_ADD_LINE(m, "A14x=%d ", hw_cnt->aft_serial_adapters);
}
if (hw_cnt->aft300_adapters){
PROC_ADD_LINE(m, "A300=%d ", hw_cnt->aft300_adapters);
}
if (hw_cnt->usb_adapters){
PROC_ADD_LINE(m, "U100=%d ", hw_cnt->usb_adapters);
}
if (hw_cnt->aft_a600_adapters){
PROC_ADD_LINE(m, "B600=%d ", hw_cnt->aft_a600_adapters);
}
if (hw_cnt->aft_b601_adapters){
PROC_ADD_LINE(m, "B601=%d ", hw_cnt->aft_b601_adapters);
}
if (hw_cnt->aft_b800_adapters){
PROC_ADD_LINE(m, "B800=%d ", hw_cnt->aft_b800_adapters);
}
if (hw_cnt->aft_w400_adapters){
PROC_ADD_LINE(m, "W400=%d ", hw_cnt->aft_w400_adapters);
}
if (hw_cnt->aft116_adapters){
PROC_ADD_LINE(m, "A116=%d ", hw_cnt->aft116_adapters);
}
if (hw_cnt->aft_t116_adapters){
PROC_ADD_LINE(m, "T116=%d ", hw_cnt->aft_t116_adapters);
}
PROC_ADD_LINE(m, "\n");
PROC_ADD_RET(m);
}
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int probe_get_info_dump(char* buf, char** start, off_t offs, int len)
#else
# if defined(LINUX_2_6)
static int probe_get_info_dump(struct seq_file *m, void *v)
# elif defined(LINUX_2_4)
static int probe_get_info_dump(char* buf, char** start, off_t offs, int len)
# else
static int probe_get_info_dump(char* buf, char** start, off_t offs, int len, int dummy)
# endif
#endif
{
int i=0;
sdla_hw_probe_t* hw_probe;
sdla_hw_type_cnt_t *hw_cnt;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
if (hw_probe->index) {
if (hw_probe->index > i) {
i=hw_probe->index;
}
PROC_ADD_LINE(m,
"|%d%s\n", hw_probe->index, hw_probe->hw_info_dump);
}
}
hw_probe = (sdla_hw_probe_t *)sdla_get_hw_probe();
for (;
hw_probe;
hw_probe = WAN_LIST_NEXT(hw_probe, next)) {
if (!hw_probe->index) {
i++;
PROC_ADD_LINE(m,
"|%d%s\n", i, hw_probe->hw_info_dump);
}
}
hw_cnt=(sdla_hw_type_cnt_t*)sdla_get_hw_adptr_cnt();
PROC_ADD_LINE(m,
"|Card Cnt|S508=%d|S514X=%d|S518=%d|A101-2=%d|A104=%d|A300=%d|A200=%d|A108=%d|A056=%d|A500=%d|B700=%d|B600=%d|B601=%d|A14x=%d|A116=%d|T116=%d|W400=%d|\n",
hw_cnt->s508_adapters,
hw_cnt->s514x_adapters,
hw_cnt->s518_adapters,
hw_cnt->aft101_adapters,
hw_cnt->aft104_adapters,
hw_cnt->aft300_adapters,
hw_cnt->aft200_adapters,
hw_cnt->aft108_adapters,
hw_cnt->aft_56k_adapters,
hw_cnt->aft_isdn_adapters,
hw_cnt->aft_a700_adapters,
hw_cnt->aft_a600_adapters,
hw_cnt->aft_b601_adapters,
hw_cnt->aft_serial_adapters,
hw_cnt->aft116_adapters,
hw_cnt->aft_t116_adapters,
hw_cnt->aft_w400_adapters);
PROC_ADD_RET(m);
}
/*
* Prepare data for reading <device> entry.
* Return length of data.
*
* On entry, the 'start' argument will contain a pointer to WAN device
* data space.
*/
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(LINUX_2_4)
STATIC int wandev_get_info(char* buf, char** start, off_t offs, int len)
#else
#if defined(LINUX_2_6)
static int wandev_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int wandev_get_info(char* buf, char** start, off_t offs, int len)
#else
static int wandev_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
#endif
{
wan_device_t* wandev = PROC_GET_DATA();
int rslt = 0;
PROC_ADD_DECL(m);
if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
return 0;
PROC_ADD_INIT(m, buf, offs, len);
if (!wandev->state){
PROC_ADD_LINE(m,
"device is not configured!\n");
goto wandev_get_info_end;
}
/* Update device statistics */
if (wandev->update && !m->from){
rslt = wandev->update(wandev);
if(rslt) {
switch (rslt) {
case -EAGAIN:
PROC_ADD_LINE(m,
"Device is busy!\n");
break;
default:
PROC_ADD_LINE(m,
"Device is not configured!\n");
break;
}
goto wandev_get_info_end;
}
}
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"total rx packets", wandev->stats.rx_packets,
"total tx packets", wandev->stats.tx_packets);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"total rx bytes", wandev->stats.rx_bytes,
"total tx bytes", wandev->stats.tx_bytes);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"bad rx packets", wandev->stats.rx_errors,
"packet tx problems", wandev->stats.tx_errors);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"rx frames dropped", wandev->stats.rx_dropped,
"tx frames dropped", wandev->stats.tx_dropped);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"multicast rx packets", wandev->stats.multicast,
"tx collisions", wandev->stats.collisions);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"rx length errors", wandev->stats.rx_length_errors,
"rx overrun errors", wandev->stats.rx_over_errors);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"CRC errors", wandev->stats.rx_crc_errors,
"abort frames", wandev->stats.rx_frame_errors);
PROC_ADD_LINE(m,
PROC_STATS_2_FORMAT,
"rx fifo overrun", wandev->stats.rx_fifo_errors,
"rx missed packet", wandev->stats.rx_missed_errors);
PROC_ADD_LINE(m,
PROC_STATS_1_FORMAT,
"aborted tx frames", wandev->stats.tx_aborted_errors);
/* Update Front-End information (alarms, performance monitor counters */
if (wandev->get_info){
m->count = wandev->get_info(
wandev->priv,
m,
M_STOP_CNT(m));
}
wandev_get_info_end:
PROC_ADD_RET(m);
}
#if defined(__LINUX__)
#ifdef LINUX_2_6
#define FPTR(st) (&st)
#else
#define FPTR(st) NULL
#endif
static inline struct proc_dir_entry *wp_proc_create(const char *name,
umode_t mode,
struct proc_dir_entry *parent,
struct file_operations *proc_fops)
{
struct proc_dir_entry *p = NULL;
#ifdef LINUX_3_0
p = proc_create(name, mode, parent, proc_fops);
#elif defined(LINUX_2_6)
p = create_proc_entry(name, mode, parent);
if (!p) {
return NULL;
}
p->proc_fops = proc_fops;
#elif defined(LINUX_2_4)
p = create_proc_entry(name, mode, parent);
if (!p) {
return NULL;
}
/* In 2.4 we always default to router_fops and router_inode */
if (!proc_fops) {
p->proc_fops = &router_fops;
}
p->proc_iops = &router_inode;
#else
p = create_proc_entry(name, mode, parent);
if (!p) {
return NULL;
}
/* In Pre-2.4 we always default to router_inode */
p->ops = &router_inode;
p->nlink = 1;
#endif
return p;
}
static inline struct proc_dir_entry *wp_proc_create_data(const char *name,
umode_t mode,
struct proc_dir_entry *parent,
struct file_operations *proc_fops, void *data)
{
struct proc_dir_entry *p = NULL;
#ifdef LINUX_3_0
p = proc_create_data(name, mode, parent, proc_fops, data);
#else
p = wp_proc_create(name, mode, parent, proc_fops);
if (p) {
p->data = data;
}
#endif
return p;
}
/*
* Initialize router proc interface.
*/
int wanrouter_proc_init (void)
{
struct proc_dir_entry *p;
proc_router = proc_mkdir(ROUTER_NAME, wan_init_net(proc_net));
if (!proc_router)
goto fail;
p = wp_proc_create("config",S_IRUGO,proc_router,FPTR(config_fops));
if (!p)
goto fail_config;
#ifndef LINUX_2_6
p->get_info = config_get_info;
#endif
p = wp_proc_create("status",S_IRUGO,proc_router,FPTR(status_fops));
if (!p)
goto fail_stat;
#ifndef LINUX_2_6
p->get_info = status_get_info;
#endif
p = wp_proc_create("hwprobe",0,proc_router,FPTR(wp_hwprobe_fops));
if (!p)
goto fail_probe;
#ifndef LINUX_2_6
p->get_info = probe_get_info;
#endif
p = wp_proc_create("hwprobe_legacy",0,proc_router,FPTR(wp_hwprobe_legacy_fops));
if (!p)
goto fail_probe_legacy;
#ifndef LINUX_2_6
p->get_info = probe_get_info_legacy;
#endif
p = wp_proc_create("hwprobe_verbose",0,proc_router,FPTR(wp_hwprobe_verbose_fops));
if (!p)
goto fail_probe_verbose;
#ifndef LINUX_2_6
p->get_info = probe_get_info_verbose;
#endif
p = wp_proc_create("hwprobe_dump",0,proc_router,FPTR(wp_hwprobe_dump_fops));
if (!p)
goto fail_probe_dump;
#ifndef LINUX_2_6
p->get_info = probe_get_info_dump;
#endif
p = wp_proc_create("map",0,proc_router,FPTR(wp_map_fops));
if (!p)
goto fail_map;
#ifndef LINUX_2_6
p->get_info = map_get_info;
#endif
p = wp_proc_create("interfaces",0,proc_router,FPTR(wp_iface_fops));
if (!p)
goto fail_interfaces;
#ifndef LINUX_2_6
p->get_info = interfaces_get_info;
#endif
map_dir = proc_mkdir("dev_map", proc_router);
if (!map_dir)
goto fail_dev_map;
/* Initialize protocol proc fs. */
proc_router_chdlc.count = 0;
proc_router_chdlc.protocol_entry = NULL;
proc_router_fr.count = 0;
proc_router_fr.protocol_entry = NULL;
proc_router_ppp.count = 0;
proc_router_ppp.protocol_entry = NULL;
proc_router_x25.count = 0;
proc_router_x25.protocol_entry = NULL;
return 0;
fail_dev_map:
remove_proc_entry("interfaces", proc_router);
fail_interfaces:
remove_proc_entry("map", proc_router);
fail_map:
remove_proc_entry("hwprobe_dump", proc_router);
fail_probe_dump:
remove_proc_entry("hwprobe_verbose", proc_router);
fail_probe_verbose:
remove_proc_entry("hwprobe_legacy", proc_router);
fail_probe_legacy:
remove_proc_entry("hwprobe", proc_router);
fail_probe:
remove_proc_entry("status", proc_router);
fail_stat:
remove_proc_entry("config", proc_router);
fail_config:
remove_proc_entry(ROUTER_NAME, wan_init_net(proc_net));
fail:
return -ENOMEM;
}
/*
* Clean up router proc interface.
*/
void wanrouter_proc_cleanup (void)
{
remove_proc_entry("config", proc_router);
remove_proc_entry("status", proc_router);
remove_proc_entry("hwprobe", proc_router);
remove_proc_entry("hwprobe_legacy", proc_router);
remove_proc_entry("hwprobe_verbose", proc_router);
remove_proc_entry("hwprobe_dump", proc_router);
remove_proc_entry("map", proc_router);
remove_proc_entry("interfaces", proc_router);
remove_proc_entry("dev_map",proc_router);
remove_proc_entry(ROUTER_NAME,wan_init_net(proc_net));
}
/*
* Add directory entry for WAN device.
*/
int wanrouter_proc_add (wan_device_t* wandev)
{
int err=0;
struct proc_dir_entry *p;
wan_spin_lock_init(&wandev->get_map_lock, "wan_proc_lock");
if (wandev->magic != ROUTER_MAGIC)
return -EINVAL;
wandev->dent = wp_proc_create_data(wandev->name, S_IRUGO, proc_router, FPTR(wandev_fops), wandev);
if (!wandev->dent)
return -ENOMEM;
#if !defined(LINUX_2_6)
wandev->dent->get_info = wandev_get_info;
#endif
p = wp_proc_create_data(wandev->name, 0, map_dir, FPTR(wandev_mapdir_fops), wandev);
if (!p){
remove_proc_entry(wandev->name, proc_router);
wandev->dent=NULL;
return -ENOMEM;
}
#if !defined(LINUX_2_6)
#if defined(LINUX_2_4)
p->proc_fops = &wandev_fops;
p->proc_iops = &router_inode;
p->get_info = wandev_mapdir_get_info;
#else
p->ops = &wandev_inode;
p->get_info = wandev_mapdir_get_info;
#endif
#endif
return err;
}
/*
* Delete directory entry for WAN device.
*/
int wanrouter_proc_delete(wan_device_t* wandev)
{
if (wandev->magic != ROUTER_MAGIC)
return -EINVAL;
remove_proc_entry(wandev->name, proc_router);
remove_proc_entry(wandev->name, map_dir);
return 0;
}
/*
* Add directory entry for Protocol.
*/
int wanrouter_proc_add_protocol(wan_device_t* wandev)
{
struct proc_dir_entry* p = NULL;
//struct proc_dir_entry** proc_protocol;
wan_proc_entry_t* proc_protocol;
if (wandev->magic != ROUTER_MAGIC)
return -EINVAL;
switch(wandev->config_id){
case WANCONFIG_FR:
case WANCONFIG_MFR:
proc_protocol = &proc_router_fr;
break;
case WANCONFIG_CHDLC:
proc_protocol = &proc_router_chdlc;
break;
case WANCONFIG_PPP:
proc_protocol = &proc_router_ppp;
break;
case WANCONFIG_X25:
proc_protocol = &proc_router_x25;
break;
default:
proc_protocol = NULL;
return 0;
}
if (proc_protocol->protocol_entry == NULL){
proc_protocol->count=0;
/* Create /proc/net/wanrouter/<protocol> directory */
proc_protocol->protocol_entry =
proc_mkdir(PROT_DECODE(wandev->config_id,0), proc_router);
if (!proc_protocol->protocol_entry)
goto fail;
/* Create /proc/net/wanrouter/<protocol>/config directory */
p = wp_proc_create_data("config",0,proc_protocol->protocol_entry,FPTR(wp_get_dev_config_fops),((void *)(long)wandev->config_id));
if (!p)
goto fail_config;
#if !defined(LINUX_2_6)
p->get_info = get_dev_config_info;
#endif
/* Create /proc/net/wanrouter/<protocol>/status directory */
p = wp_proc_create_data("status",0,proc_protocol->protocol_entry,FPTR(wp_get_dev_status_fops),((void *)(long)wandev->config_id));
if (!p)
goto fail_stat;
#if !defined(LINUX_2_6)
p->get_info = get_dev_status_info;
#endif
}
/* Create /proc/net/wanrouter/<protocol>/<wanpipe#> directory */
wandev->link = proc_mkdir(wandev->name, proc_protocol->protocol_entry);
if (!wandev->link)
goto fail_link;
/* Create /proc/net/wanrouter/<protocol>/<wanpipe#>config directory */
p = wp_proc_create_data("config",0,wandev->link,NULL,wandev);
if (!p)
goto fail_link_config;
#if !defined(LINUX_2_6)
p->get_info = wandev->get_dev_config_info;
p->write_proc = wandev->set_dev_config;
#endif
proc_protocol->count ++;
return 0;
fail_link_config:
remove_proc_entry(wandev->name, proc_protocol->protocol_entry);
fail_link:
if (proc_protocol->count){
/* Do not remove /proc/net/wanrouter/<protocol>... because
* another device is still using this entry.
*/
return -ENOMEM;
}
remove_proc_entry("status", proc_protocol->protocol_entry);
return -ENOMEM;
fail_stat:
remove_proc_entry("config", proc_protocol->protocol_entry);
fail_config:
remove_proc_entry(PROT_DECODE(wandev->config_id,0), proc_router);
proc_protocol->protocol_entry = NULL;
fail:
return -ENOMEM;
}
/*
* Delete directory entry for Protocol.
*/
int wanrouter_proc_delete_protocol(wan_device_t* wandev)
{
wan_proc_entry_t* proc_protocol = NULL;
if (wandev->magic != ROUTER_MAGIC)
return -EINVAL;
switch(wandev->config_id){
case WANCONFIG_FR:
case WANCONFIG_MFR:
proc_protocol = &proc_router_fr;
break;
case WANCONFIG_CHDLC:
proc_protocol = &proc_router_chdlc;
break;
case WANCONFIG_PPP:
proc_protocol = &proc_router_ppp;
break;
case WANCONFIG_X25:
proc_protocol = &proc_router_x25;
break;
default:
proc_protocol = NULL;
return 0;
break;
}
remove_proc_entry("config", wandev->link);
remove_proc_entry(wandev->name, proc_protocol->protocol_entry);
proc_protocol->count --;
if (!proc_protocol->count){
remove_proc_entry("config", proc_protocol->protocol_entry);
remove_proc_entry("status", proc_protocol->protocol_entry);
remove_proc_entry(PROT_DECODE(wandev->config_id,0), proc_router);
proc_protocol->protocol_entry = NULL;
}
return 0;
}
/*
* Add directory entry for interface.
*/
int wanrouter_proc_add_interface(wan_device_t* wandev,
struct proc_dir_entry** dent,
char* if_name,
void* priv)
{
#if 0
if (wandev->magic != ROUTER_MAGIC)
return -EINVAL;
if (wandev->link == NULL || wandev->get_if_info == NULL)
return -ENODEV;
*dent = create_proc_entry(if_name, 0, wandev->link);
if (!*dent)
return -ENOMEM;
#ifdef LINUX_2_4
(*dent)->proc_fops = &router_fops;
(*dent)->proc_iops = &router_inode;
#else
(*dent)->ops = &router_inode;
(*dent)->nlink = 1;
#endif
(*dent)->get_info = wandev->get_if_info;
(*dent)->write_proc = wandev->set_if_info;
(*dent)->data = priv;
#endif
return 0;
}
/*
* Delete directory entry for interface.
*/
int wanrouter_proc_delete_interface(wan_device_t* wandev, char* if_name)
{
#if 0
if (wandev->magic != ROUTER_MAGIC)
return -EINVAL;
if (wandev->link == NULL)
return -ENODEV;
remove_proc_entry(if_name, wandev->link);
#endif
return 0;
}
/****** Proc filesystem entry points ****************************************/
/*
* Verify access rights.
*/
#ifndef LINUX_2_6
static int router_proc_perms (struct inode* inode, int op)
{
return 0;
}
/*
* Read router proc directory entry.
* This is universal routine for reading all entries in /proc/net/wanrouter
* directory. Each directory entry contains a pointer to the 'method' for
* preparing data for that entry.
* o verify arguments
* o allocate kernel buffer
* o call get_info() to prepare data
* o copy data to user space
* o release kernel buffer
*
* Return: number of bytes copied to user space (0, if no data)
* <0 error
*/
static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
struct proc_dir_entry* dent;
char* page;
int len;
if (count <= 0)
return 0;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
dent = inode->i_private;
#else
dent = inode->u.generic_ip;
#endif
if ((dent == NULL) || (dent->get_info == NULL))
return 0;
page = wan_malloc(count);
if (page == NULL)
return -ENOBUFS;
#ifdef LINUX_2_4
len = dent->get_info(page, dent->data, file->f_pos, count);
#else
len = dent->get_info(page, dent->data, file->f_pos, count, 0);
#endif
if (len) {
if(copy_to_user(buf, page, len)){
DEBUG_SUB_MEM(count);
wan_free(page);
return -EFAULT;
}
file->f_pos += len;
}
wan_free(page);
return len;
}
/*
* Write router proc directory entry.
* This is universal routine for writing all entries in /proc/net/wanrouter
* directory. Each directory entry contains a pointer to the 'method' for
* preparing data for that entry.
* o verify arguments
* o allocate kernel buffer
* o copy data from user space
* o call write_info()
* o release kernel buffer
*
* Return: number of bytes copied to user space (0, if no data)
* <0 error
*/
static ssize_t router_proc_write (struct file *file, const char *buf, size_t count,
loff_t *ppos)
{
struct inode* inode = file->f_dentry->d_inode;
struct proc_dir_entry* dent = NULL;
char* page = NULL;
#ifdef WAN_DEBUG_MEM
unsigned int ocount=count;
#endif
if (count <= 0)
return 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
dent = inode->i_private;
#else
dent = inode->u.generic_ip;
#endif
if ((dent == NULL) || (dent->write_proc == NULL))
return count;
page = wan_malloc(count);
if (page == NULL)
return -ENOBUFS;
if (copy_from_user(page, buf, count)){
DEBUG_SUB_MEM(count);
wan_free(page);
return -EINVAL;
}
page[count-1] = '\0';
/* Add supporting Write to proc fs */
count = dent->write_proc(file, page, count, dent->data);
DEBUG_SUB_MEM(ocount);
wan_free(page);
return count;
}
#endif
/*
* Prepare data for reading 'MAP' entry.
* Return length of data.
*/
#if defined(LINUX_2_6)
static int map_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int map_get_info(char* buf, char** start, off_t offs, int len)
#else
static int map_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
{
wan_device_t* wandev = NULL;
struct wan_dev_le *devle;
netdevice_t* dev=NULL;
wan_smp_flag_t flags;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "%s", map_hdr);
wan_spin_lock(&wan_devlist_lock,&flags);
WAN_LIST_FOREACH(wandev, &wan_devlist, next){
if (!wandev->state){
continue;
}
if (!wandev->get_map){
continue;
}
wan_spin_lock(&wandev->dev_head_lock,&flags);
WAN_LIST_FOREACH(devle, &wandev->dev_head, dev_link){
dev = WAN_DEVLE2DEV(devle);
if (!dev || !(dev->flags&IFF_UP) || !wan_netif_priv(dev)){
continue;
}
m->count = wandev->get_map(wandev, dev, m, M_STOP_CNT(m));
}
wan_spin_unlock(&wandev->dev_head_lock,&flags);
}
wan_spin_unlock(&wan_devlist_lock,&flags);
PROC_ADD_RET(m);
}
/*
* Prepare data for reading FR 'Config' entry.
* Return length of data.
*/
#if defined(LINUX_2_6)
static int get_dev_config_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int get_dev_config_info(char* buf, char** start, off_t offs, int len)
#else
static int get_dev_config_info(char* buf, char** start, off_t offs, int len,int dummy)
#endif
{
wan_device_t* wandev = NULL;
netdevice_t* dev = NULL;
wan_smp_flag_t flags;
struct wan_dev_le *devle;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
wan_spin_lock(&wan_devlist_lock,&flags);
WAN_LIST_FOREACH(wandev, &wan_devlist, next){
if (!(m->count < (PROC_BUFSZ - 80))) break;
if (!wandev->get_config_info)
continue;
#ifndef LINUX_2_6
if ((wandev->config_id != (unsigned)start) || !wandev->state)
continue;
#else
if (!wandev->state)
continue;
#endif
wan_spin_lock(&wandev->dev_head_lock,&flags);
WAN_LIST_FOREACH(devle, &wandev->dev_head, dev_link){
dev = WAN_DEVLE2DEV(devle);
if (!dev || !(dev->flags&IFF_UP) || !wan_netif_priv(dev)){
continue;
}
m->count = wandev->get_config_info(wan_netif_priv(dev),
m,
M_STOP_CNT(m));
}
wan_spin_unlock(&wandev->dev_head_lock,&flags);
}
wan_spin_unlock(&wan_devlist_lock,&flags);
PROC_ADD_RET(m);
}
/*
* Prepare data for reading FR 'Status' entry.
* Return length of data.
*/
#if defined(LINUX_2_6)
static int get_dev_status_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int get_dev_status_info(char* buf, char** start, off_t offs, int len)
#else
static int get_dev_status_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
{
wan_device_t* wandev = NULL;
struct wan_dev_le *devle;
netdevice_t* dev = NULL;
int cnt = 0;
wan_smp_flag_t flags;
PROC_ADD_DECL(m);
PROC_ADD_INIT(m, buf, offs, len);
wan_spin_lock(&wan_devlist_lock,&flags);
WAN_LIST_FOREACH(wandev, &wan_devlist, next){
if (!(cnt < (PROC_BUFSZ - 80))) break;
if (!wandev->get_status_info)
continue;
#ifndef LINUX_2_6
if ((wandev->config_id != (unsigned)start) || !wandev->state)
continue;
#else
if (!wandev->state)
continue;
#endif
wan_spin_lock(&wandev->dev_head_lock,&flags);
WAN_LIST_FOREACH(devle, &wandev->dev_head, dev_link){
dev = WAN_DEVLE2DEV(devle);
if (!dev || !(dev->flags&IFF_UP) || !wan_netif_priv(dev)){
continue;
}
m->count = wandev->get_status_info(wan_netif_priv(dev), m, M_STOP_CNT(m));
}
wan_spin_unlock(&wandev->dev_head_lock,&flags);
}
wan_spin_unlock(&wan_devlist_lock,&flags);
PROC_ADD_RET(m);
}
#if defined(LINUX_2_6)
static int wandev_mapdir_get_info(struct seq_file *m, void *v)
#elif defined(LINUX_2_4)
static int wandev_mapdir_get_info(char* buf, char** start, off_t offs, int len)
#else
static int wandev_mapdir_get_info(char* buf, char** start, off_t offs, int len, int dummy)
#endif
{
wan_device_t* wandev = PROC_GET_DATA();
struct wan_dev_le *devle;
netdevice_t* dev = NULL;
wan_smp_flag_t flags;
PROC_ADD_DECL(m);
if (!wandev){
return -ENODEV;
}
PROC_ADD_INIT(m, buf, offs, len);
PROC_ADD_LINE(m, "%s", map_hdr);
if (!wandev->state){
goto wandev_mapdir_get_info_exit;
}
if (!wandev->get_map){
goto wandev_mapdir_get_info_exit;
}
wan_spin_lock(&wandev->dev_head_lock,&flags);
WAN_LIST_FOREACH(devle, &wandev->dev_head, dev_link){
dev = WAN_DEVLE2DEV(devle);
if (!dev || !(dev->flags&IFF_UP) || !wan_netif_priv(dev)){
continue;
}
m->count = wandev->get_map(wandev, dev, m, M_STOP_CNT(m));
}
wan_spin_unlock(&wandev->dev_head_lock,&flags);
wandev_mapdir_get_info_exit:
PROC_ADD_RET(m);
}
#endif /* __LINUX__ */
#else
/*
* No /proc - output stubs
*/
int wanrouter_proc_init(void)
{
return 0;
}
void wanrouter_proc_cleanup(void)
{
return;
}
int wanrouter_proc_add(wan_device_t *wandev)
{
return 0;
}
int wanrouter_proc_delete(wan_device_t *wandev)
{
return 0;
}
int wanrouter_proc_add_protocol(wan_device_t *wandev)
{
return 0;
}
int wanrouter_proc_delete_protocol(wan_device_t *wandev)
{
return 0;
}
int wanrouter_proc_add_interface(wan_device_t* wandev,
struct proc_dir_entry** dent,
char* if_name,
void* priv)
{
return 0;
}
int wanrouter_proc_delete_interface(wan_device_t* wandev, char* if_name)
{
return 0;
}
#endif
/*============================================================================
* Write WAN device ???.
* o Find WAN device associated with this node
*/
#ifdef LINUX_2_0
static int device_write(
struct inode* inode, struct file* file, const char* buf, int count)
{
int err = verify_area(VERIFY_READ, buf, count);
struct proc_dir_entry* dent;
wan_device_t* wandev;
if (err) return err;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
dent = inode->i_private;
#else
dent = inode->u.generic_ip;
#endif
if ((dent == NULL) || (dent->data == NULL))
return -ENODATA;
wandev = dent->data;
DEBUG_TEST("%s: writing %d bytes to %s...\n",
name_root, count, dent->name);
return 0;
}
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
int proc_add_line(struct seq_file* m, char* frm, ...)
{
char tmp[400];
int ret = PROC_BUF_CONT;
int size = 0;
va_list arg;
va_start(arg, frm);
if (m->count && m->stop_cnt){
va_end(arg);
return PROC_BUF_EXIT;
}
size = vsprintf(tmp, frm, arg);
if (m->stop_cnt){
if (m->stop_cnt < size){
DEBUG_ERROR("!!! Error in writting in proc buffer !!!\n");
m->stop_cnt = size;
}
m->stop_cnt -= size;
}else{
if (size < m->size - m->count){
/*vsprintf(&m->buf[m->count], frm, arg);*/
memcpy(&m->buf[m->count], tmp, size);
m->count += size;
/* *cnt += vsprintf(&buf[*cnt], frm, arg); */
}else{
m->stop_cnt = m->from + m->count;
ret = PROC_BUF_EXIT;
}
}
va_end(arg);
return ret;
}
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#else
int proc_add_line(struct seq_file* m, char* frm, ...)
{
#if defined(LINUX_2_6)
return 0;
#else
char tmp[400];
int ret = PROC_BUF_CONT;
int size = 0;
va_list arg;
va_start(arg, frm);
if (m->count && m->stop_cnt){
va_end(arg);
return PROC_BUF_EXIT;
}
size = vsprintf(tmp, frm, arg);
if (m->stop_cnt){
if (m->stop_cnt < size){
DEBUG_ERROR("!!! Error in writting in proc buffer !!!\n");
m->stop_cnt = size;
}
m->stop_cnt -= size;
}else{
if (size < m->size - m->count){
/*vsprintf(&m->buf[m->count], frm, arg);*/
memcpy(&m->buf[m->count], tmp, size);
m->count += size;
/* *cnt += vsprintf(&buf[*cnt], frm, arg); */
}else{
m->stop_cnt = m->from + m->count;
ret = PROC_BUF_EXIT;
}
}
va_end(arg);
return ret;
#endif
}
#endif
#endif /* !__WINDOWS__ */
/*
* End
*/