patch-2.4.4 linux/net/wanrouter/wanproc.c
Next file: linux/net/x25/af_x25.c
Previous file: linux/net/wanrouter/wanmain.c
Back to the patch index
Back to the overall index
- Lines: 1380
- Date:
Thu Apr 12 12:11:39 2001
- Orig file:
v2.4.3/linux/net/wanrouter/wanproc.c
- Orig date:
Fri Feb 9 11:34:13 2001
diff -u --recursive --new-file v2.4.3/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
@@ -13,7 +13,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
-* Jan 20, 2001 Arnaldo C.Melo Fix leak on error in router_proc_read, cleanups
* 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
@@ -26,397 +25,1017 @@
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/kernel.h>
-#include <linux/slab.h> /* kmalloc(), kfree() */
+#include <linux/malloc.h> /* kmalloc(), kfree() */
#include <linux/mm.h> /* verify_area(), etc. */
#include <linux/string.h> /* inline mem*, str* functions */
-#include <linux/init.h> /* __init et al. */
-#include <asm/segment.h> /* kernel <-> user copy */
#include <asm/byteorder.h> /* htons(), etc. */
-#include <asm/uaccess.h> /* copy_to_user */
#include <asm/io.h>
#include <linux/wanrouter.h> /* WAN router API definitions */
-/****** Defines and Macros **************************************************/
-#define PROC_STATS_FORMAT "%30s: %12lu\n"
+#if defined(LINUX_2_1) || defined(LINUX_2_4)
+ #include <linux/init.h> /* __initfunc et al. */
+ #include <asm/uaccess.h> /* copy_to_user */
+ #define PROC_STATS_FORMAT "%30s: %12lu\n"
+#else
+ #define PROC_STATS_FORMAT "%30s: %12u\n"
+ #include <asm/segment.h> /* kernel <-> user copy */
+#endif
+
+
+/****** Defines and Macros **************************************************/
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
#define PROC_BUFSZ 4000 /* buffer size for printing proc info */
+#define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
+ (prot == WANCONFIG_X25) ? " X25" : \
+ (prot == WANCONFIG_PPP) ? " PPP" : \
+ (prot == WANCONFIG_CHDLC) ? " CHDLC": \
+ (prot == WANCONFIG_MPPP) ? " MPPP" : \
+ " Unknown" )
+
+/****** Data Types **********************************************************/
+
+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;
+
/****** Function Prototypes *************************************************/
#ifdef CONFIG_PROC_FS
-/* Proc filesystem interface */
-static int router_proc_perms(struct inode *, int);
-static ssize_t router_proc_read(struct file* file, char* buf, size_t count, loff_t *ppos);
-/* Methods for preparing data for reading proc entries */
+#ifdef LINUX_2_4 /* Start of LINUX 2.4.X code */
-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 wandev_get_info(char* buf, char** start, off_t offs, int len);
-/* Miscellaneous */
+ /* Proc filesystem interface */
+ static int router_proc_perms(struct inode *, int);
+ static ssize_t router_proc_read(struct file* file, char* buf, size_t count, loff_t *ppos);
+
+ /* Methods for preparing data for reading proc entries */
+
+ 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 wandev_get_info(char* buf, char** start, off_t offs, int len);
+
+ /* Miscellaneous */
+
+ /*
+ * Structures for interfacing with the /proc filesystem.
+ * Router creates its own directory /proc/net/router with the folowing
+ * entries:
+ * config device configuration
+ * status global device statistics
+ * <device> entry for each WAN device
+ */
+
+ /*
+ * Generic /proc/net/router/<file> file and inode operations
+ */
+ static struct file_operations router_fops =
+ {
+ read: router_proc_read,
+ };
+
+ static struct inode_operations router_inode =
+ {
+ permission: router_proc_perms,
+ };
+
+ /*
+ * /proc/net/router/<device> file operations
+ */
+
+ static struct file_operations wandev_fops =
+ {
+ read: router_proc_read,
+ ioctl: wanrouter_ioctl,
+ };
+
+ /*
+ * /proc/net/router
+ */
+
+ static struct proc_dir_entry *proc_router;
+
+ /* Strings */
+ static char conf_hdr[] =
+ "Device name | port |IRQ|DMA| mem.addr |mem.size|"
+ "option1|option2|option3|option4\n";
+
+ static char stat_hdr[] =
+ "Device name |protocol|station|interface|clocking|baud rate"
+ "| MTU |ndev|link state\n";
+
+
+ /*
+ * Interface functions
+ */
+
+ /*
+ * Initialize router proc interface.
+ */
+
+ int __init wanrouter_proc_init (void)
+ {
+ struct proc_dir_entry *p;
+ proc_router = proc_mkdir(ROUTER_NAME, proc_net);
+ if (!proc_router)
+ goto fail;
+
+ p = create_proc_entry("config",0,proc_router);
+ if (!p)
+ goto fail_config;
+ p->proc_fops = &router_fops;
+ p->proc_iops = &router_inode;
+ p->get_info = config_get_info;
+ p = create_proc_entry("status",0,proc_router);
+ if (!p)
+ goto fail_stat;
+ p->proc_fops = &router_fops;
+ p->proc_iops = &router_inode;
+ p->get_info = status_get_info;
+ return 0;
+ fail_stat:
+ remove_proc_entry("config", proc_router);
+ fail_config:
+ remove_proc_entry(ROUTER_NAME, proc_net);
+ fail:
+ return -ENOMEM;
+ }
-/*
- * 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
- */
+ /*
+ * 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(ROUTER_NAME,proc_net);
+ }
-/*
- * Generic /proc/net/wanrouter/<file> file and inode operations
- */
-static struct file_operations router_fops =
-{
- read: router_proc_read,
-};
+ /*
+ * Add directory entry for WAN device.
+ */
+
+ int wanrouter_proc_add (wan_device_t* wandev)
+ {
+ if (wandev->magic != ROUTER_MAGIC)
+ return -EINVAL;
+
+ wandev->dent = create_proc_entry(wandev->name, 0, proc_router);
+ if (!wandev->dent)
+ return -ENOMEM;
+ wandev->dent->proc_fops = &wandev_fops;
+ wandev->dent->proc_iops = &router_inode;
+ wandev->dent->get_info = wandev_get_info;
+ wandev->dent->data = wandev;
+ return 0;
+ }
-static struct inode_operations router_inode =
-{
- permission: router_proc_perms,
-};
+ /*
+ * 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);
+ return 0;
+ }
-/*
- * /proc/net/wanrouter/<device> file operations
- */
+ /****** Proc filesystem entry points ****************************************/
-static struct file_operations wandev_fops =
-{
- read: router_proc_read,
- ioctl: wanrouter_ioctl,
-};
+ /*
+ * Verify access rights.
+ */
-/*
- * /proc/net/wanrouter
- */
+ static int router_proc_perms (struct inode* inode, int op)
+ {
+ return 0;
+ }
-static struct proc_dir_entry *proc_router;
+ /*
+ * 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 pos, offs, len;
+
+ if (count <= 0)
+ return 0;
+
+ dent = inode->u.generic_ip;
+ if ((dent == NULL) || (dent->get_info == NULL))
+ return 0;
+
+ page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
+ if (page == NULL)
+ return -ENOBUFS;
+
+ pos = dent->get_info(page, dent->data, 0, 0);
+ offs = file->f_pos;
+ if (offs < pos) {
+ len = min(pos - offs, count);
+ if(copy_to_user(buf, (page + offs), len))
+ return -EFAULT;
+ file->f_pos += len;
+ }
+ else
+ len = 0;
+ kfree(page);
+ return len;
+ }
-/* Strings */
-static char conf_hdr[] =
- "Device name | port |IRQ|DMA| mem.addr |mem.size|"
- "option1|option2|option3|option4\n";
-
-static char stat_hdr[] =
- "Device name |station|interface|clocking|baud rate| MTU |ndev"
- "|link state\n";
+ /*
+ * Prepare data for reading 'Config' entry.
+ * Return length of data.
+ */
+
+ static int config_get_info(char* buf, char** start, off_t offs, int len)
+ {
+ int cnt = sizeof(conf_hdr) - 1;
+ wan_device_t* wandev;
+ strcpy(buf, conf_hdr);
+ for (wandev = router_devlist;
+ wandev && (cnt < (PROC_BUFSZ - 120));
+ wandev = wandev->next) {
+ if (wandev->state) cnt += sprintf(&buf[cnt],
+ "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
+ wandev->name,
+ wandev->ioport,
+ wandev->irq,
+ wandev->dma,
+ wandev->maddr,
+ wandev->msize,
+ wandev->hw_opt[0],
+ wandev->hw_opt[1],
+ wandev->hw_opt[2],
+ wandev->hw_opt[3]);
+ }
+ return cnt;
+ }
-/*
- * Interface functions
- */
+ /*
+ * Prepare data for reading 'Status' entry.
+ * Return length of data.
+ */
+
+ static int status_get_info(char* buf, char** start, off_t offs, int len)
+ {
+ int cnt = 0;
+ wan_device_t* wandev;
+
+ //cnt += sprintf(&buf[cnt], "\nSTATUS:\n\n");
+ strcpy(&buf[cnt], stat_hdr);
+ cnt += sizeof(stat_hdr) - 1;
+
+ for (wandev = router_devlist;
+ wandev && (cnt < (PROC_BUFSZ - 80));
+ wandev = wandev->next) {
+ if (!wandev->state) continue;
+ cnt += sprintf(&buf[cnt],
+ "%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
+ wandev->name,
+ PROT_DECODE(wandev->config_id),
+ wandev->config_id == WANCONFIG_FR ?
+ (wandev->station ? " Node" : " CPE") :
+ (wandev->config_id == WANCONFIG_X25 ?
+ (wandev->station ? " DCE" : " DTE") :
+ (" N/A")),
+ wandev->interface ? " V.35" : " RS-232",
+ wandev->clocking ? "internal" : "external",
+ wandev->bps,
+ wandev->mtu,
+ wandev->ndev);
+
+ switch (wandev->state) {
+
+ case WAN_UNCONFIGURED:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
+ break;
+
+ case WAN_DISCONNECTED:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
+ break;
+
+ case WAN_CONNECTING:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
+ break;
+
+ case WAN_CONNECTED:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
+ break;
-/*
- * Initialize router proc interface.
- */
+ default:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
+ break;
+ }
+ }
+ return cnt;
+ }
-int __init wanrouter_proc_init (void)
-{
- struct proc_dir_entry *p;
- proc_router = proc_mkdir(ROUTER_NAME, proc_net);
- if (!proc_router)
- goto fail;
-
- p = create_proc_entry("config",0,proc_router);
- if (!p)
- goto fail_config;
- p->proc_fops = &router_fops;
- p->proc_iops = &router_inode;
- p->get_info = config_get_info;
- p = create_proc_entry("status",0,proc_router);
- if (!p)
- goto fail_stat;
- p->proc_fops = &router_fops;
- p->proc_iops = &router_inode;
- p->get_info = status_get_info;
- return 0;
-fail_stat:
- remove_proc_entry("config", proc_router);
-fail_config:
- remove_proc_entry(ROUTER_NAME, proc_net);
-fail:
- return -ENOMEM;
-}
+ /*
+ * Prepare data for reading <device> entry.
+ * Return length of data.
+ *
+ * On entry, the 'start' argument will contain a pointer to WAN device
+ * data space.
+ */
+
+ static int wandev_get_info(char* buf, char** start, off_t offs, int len)
+ {
+ wan_device_t* wandev = (void*)start;
+ int cnt = 0;
+ int rslt = 0;
+
+ if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
+ return 0;
+ if (!wandev->state)
+ return sprintf(&buf[cnt], "device is not configured!\n");
+
+ /* Update device statistics */
+ if (wandev->update) {
+
+ rslt = wandev->update(wandev);
+ if(rslt) {
+ switch (rslt) {
+ case -EAGAIN:
+ return sprintf(&buf[cnt], "Device is busy!\n");
+
+ default:
+ return sprintf(&buf[cnt],
+ "Device is not configured!\n");
+ }
+ }
+ }
-/*
- * Clean up router proc interface.
- */
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total packets received", wandev->stats.rx_packets);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total packets transmitted", wandev->stats.tx_packets);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total bytes received", wandev->stats.rx_bytes);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total bytes transmitted", wandev->stats.tx_bytes);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "bad packets received", wandev->stats.rx_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "packet transmit problems", wandev->stats.tx_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "received frames dropped", wandev->stats.rx_dropped);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "transmit frames dropped", wandev->stats.tx_dropped);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "multicast packets received", wandev->stats.multicast);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "transmit collisions", wandev->stats.collisions);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receive length errors", wandev->stats.rx_length_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receiver overrun errors", wandev->stats.rx_over_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "CRC errors", wandev->stats.rx_crc_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "frame format errors (aborts)", wandev->stats.rx_frame_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receiver fifo overrun", wandev->stats.rx_fifo_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receiver missed packet", wandev->stats.rx_missed_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "aborted frames transmitted", wandev->stats.tx_aborted_errors);
+ return cnt;
+ }
-void wanrouter_proc_cleanup (void)
-{
- remove_proc_entry("config", proc_router);
- remove_proc_entry("status", proc_router);
- remove_proc_entry(ROUTER_NAME,proc_net);
-}
-/*
- * Add directory entry for WAN device.
- */
+#else /* ------------------- END OF LINUX 2.4.X VERSION -------------*/
-int wanrouter_proc_add (wan_device_t* wandev)
-{
- if (wandev->magic != ROUTER_MAGIC)
- return -EINVAL;
-
- wandev->dent = create_proc_entry(wandev->name, 0, proc_router);
- if (!wandev->dent)
- return -ENOMEM;
- wandev->dent->proc_fops = &wandev_fops;
- wandev->dent->proc_iops = &router_inode;
- wandev->dent->get_info = wandev_get_info;
- wandev->dent->data = wandev;
- return 0;
-}
-/*
- * 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);
- return 0;
-}
-/****** Proc filesystem entry points ****************************************/
+ /* Proc filesystem interface */
+ static int router_proc_perms(struct inode *, int);
+#ifdef LINUX_2_1
+ static ssize_t router_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
+#else
+ static int router_proc_read(
+ struct inode* inode, struct file* file, char* buf, int count);
+ static int device_write(
+ struct inode* inode, struct file* file, const char* buf, int count);
+#endif
-/*
- * Verify access rights.
- */
+ /* Methods for preparing data for reading proc entries */
+ 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 wandev_get_info(char* buf, char** start, off_t offs, int len,
+ int dummy);
+
+ /* Miscellaneous */
+
+ /*
+ * Global Data
+ */
+
+ /*
+ * Names of the proc directory entries
+ */
+
+ static char name_root[] = ROUTER_NAME;
+ static char name_conf[] = "config";
+ static char name_stat[] = "status";
+
+ /*
+ * Structures for interfacing with the /proc filesystem.
+ * Router creates its own directory /proc/net/router with the folowing
+ * entries:
+ * config device configuration
+ * status global device statistics
+ * <device> entry for each WAN device
+ */
+
+ /*
+ * Generic /proc/net/router/<file> file and inode operations
+ */
+#ifdef LINUX_2_1
+ static struct file_operations router_fops =
+ {
+ NULL, /* lseek */
+ router_proc_read, /* read */
+ NULL, /* 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 */
+ };
+#else
+ static struct file_operations router_fops =
+ {
+ NULL, /* lseek */
+ router_proc_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+ };
+#endif
-static int router_proc_perms (struct inode* inode, int op)
-{
- return 0;
-}
+ 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
+ };
+
+ /*
+ * /proc/net/router/<device> file and inode operations
+ */
+
+#ifdef LINUX_2_1
+ 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 */
+ };
+#else
+ static struct file_operations wandev_fops =
+ {
+ NULL, /* lseek */
+ router_proc_read, /* read */
+ device_write, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ wanrouter_ioctl, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+ };
+#endif
-/*
- * 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 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
+ };
+
+ /*
+ * Proc filesystem derectory entries.
+ */
+
+ /*
+ * /proc/net/router
+ */
+
+ static struct proc_dir_entry proc_router =
+ {
+ 0, /* .low_ino */
+ sizeof(name_root) - 1, /* .namelen */
+ name_root, /* .name */
+ 0555 | S_IFDIR, /* .mode */
+ 2, /* .nlink */
+ 0, /* .uid */
+ 0, /* .gid */
+ 0, /* .size */
+ &proc_dir_inode_operations, /* .ops */
+ NULL, /* .get_info */
+ NULL, /* .fill_node */
+ NULL, /* .next */
+ NULL, /* .parent */
+ NULL, /* .subdir */
+ NULL, /* .data */
+ };
+
+ /*
+ * /proc/net/router/config
+ */
+
+ static struct proc_dir_entry proc_router_conf =
+ {
+ 0, /* .low_ino */
+ sizeof(name_conf) - 1, /* .namelen */
+ name_conf, /* .name */
+ 0444 | S_IFREG, /* .mode */
+ 1, /* .nlink */
+ 0, /* .uid */
+ 0, /* .gid */
+ 0, /* .size */
+ &router_inode, /* .ops */
+ &config_get_info, /* .get_info */
+ NULL, /* .fill_node */
+ NULL, /* .next */
+ NULL, /* .parent */
+ NULL, /* .subdir */
+ NULL, /* .data */
+ };
+
+ /*
+ * /proc/net/router/status
+ */
+
+ static struct proc_dir_entry proc_router_stat =
+ {
+ 0, /* .low_ino */
+ sizeof(name_stat) - 1, /* .namelen */
+ name_stat, /* .name */
+ 0444 | S_IFREG, /* .mode */
+ 1, /* .nlink */
+ 0, /* .uid */
+ 0, /* .gid */
+ 0, /* .size */
+ &router_inode, /* .ops */
+ status_get_info, /* .get_info */
+ NULL, /* .fill_node */
+ NULL, /* .next */
+ NULL, /* .parent */
+ NULL, /* .subdir */
+ NULL, /* .data */
+ };
+
+ /* Strings */
+ static char conf_hdr[] =
+ "Device name | port |IRQ|DMA| mem.addr |mem.size|"
+ "option1|option2|option3|option4\n";
+
+ static char stat_hdr[] =
+ "Device name |protocol|station|interface|clocking|baud rate| MTU |ndev"
+ "|link state\n";
+
+
+ /*
+ * Interface functions
+ */
+
+ /*
+ * Initialize router proc interface.
+ */
+
+#ifdef LINUX_2_1
+ __initfunc(int wanrouter_proc_init (void))
+ {
+ int err = proc_register(proc_net, &proc_router);
+
+ if (!err) {
+ proc_register(&proc_router, &proc_router_conf);
+ proc_register(&proc_router, &proc_router_stat);
+ }
+ return err;
+ }
+#else
+ int wanrouter_proc_init (void)
+ {
+ int err = proc_register_dynamic(&proc_net, &proc_router);
+
+ if (!err) {
+ proc_register_dynamic(&proc_router, &proc_router_conf);
+ proc_register_dynamic(&proc_router, &proc_router_stat);
+ }
+ return err;
+ }
+#endif
-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 pos, offs, len;
+ /*
+ * Clean up router proc interface.
+ */
+
+ void wanrouter_proc_cleanup (void)
+ {
+ proc_unregister(&proc_router, proc_router_conf.low_ino);
+ proc_unregister(&proc_router, proc_router_stat.low_ino);
+#ifdef LINUX_2_1
+ proc_unregister(proc_net, proc_router.low_ino);
+#else
+ proc_unregister(&proc_net, proc_router.low_ino);
+#endif
+ }
- if (count <= 0)
- return 0;
-
- dent = inode->u.generic_ip;
- if ((dent == NULL) || (dent->get_info == NULL))
- return 0;
+ /*
+ * Add directory entry for WAN device.
+ */
+
+ int wanrouter_proc_add (wan_device_t* wandev)
+ {
+ if (wandev->magic != ROUTER_MAGIC)
+ return -EINVAL;
- page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
- if (page == NULL)
- return -ENOBUFS;
-
- pos = dent->get_info(page, dent->data, 0, 0);
- offs = file->f_pos;
- if (offs < pos) {
- len = min(pos - offs, count);
- if(copy_to_user(buf, (page + offs), len)) {
- len = -EFAULT;
- goto out;
- }
- file->f_pos += len;
- }
- else
- len = 0;
-out: kfree(page);
- return len;
-}
-
-/*
- * Prepare data for reading 'Config' entry.
- * Return length of data.
- */
+ memset(&wandev->dent, 0, sizeof(wandev->dent));
+ wandev->dent.namelen = strlen(wandev->name);
+ wandev->dent.name = wandev->name;
+ wandev->dent.mode = 0444 | S_IFREG;
+ wandev->dent.nlink = 1;
+ wandev->dent.ops = &wandev_inode;
+ wandev->dent.get_info = &wandev_get_info;
+ wandev->dent.data = wandev;
+#ifdef LINUX_2_1
+ return proc_register(&proc_router, &wandev->dent);
+#else
+ return proc_register_dynamic(&proc_router, &wandev->dent);
+#endif
+ }
-static int config_get_info(char* buf, char** start, off_t offs, int len)
-{
- int cnt = sizeof(conf_hdr) - 1;
- wan_device_t* wandev;
- strcpy(buf, conf_hdr);
- for (wandev = router_devlist;
- wandev && (cnt < (PROC_BUFSZ - 120));
- wandev = wandev->next) {
- if (wandev->state) cnt += sprintf(&buf[cnt],
- "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
- wandev->name,
- wandev->ioport,
- wandev->irq,
- wandev->dma,
- wandev->maddr,
- wandev->msize,
- wandev->hw_opt[0],
- wandev->hw_opt[1],
- wandev->hw_opt[2],
- wandev->hw_opt[3]);
+ /*
+ * Delete directory entry for WAN device.
+ */
+
+ int wanrouter_proc_delete(wan_device_t* wandev)
+ {
+ if (wandev->magic != ROUTER_MAGIC)
+ return -EINVAL;
+ proc_unregister(&proc_router, wandev->dent.low_ino);
+ return 0;
}
- return cnt;
-}
+ /****** Proc filesystem entry points ****************************************/
-/*
- * Prepare data for reading 'Status' entry.
- * Return length of data.
- */
+ /*
+ * Verify access rights.
+ */
-static int status_get_info(char* buf, char** start, off_t offs, int len)
-{
- int cnt = 0;
- wan_device_t* wandev;
+ static int router_proc_perms (struct inode* inode, int op)
+ {
+ return 0;
+ }
- cnt += sprintf(&buf[cnt], "\nSTATUS FOR PORT 0\n\n");
- strcpy(&buf[cnt], stat_hdr);
- cnt += sizeof(stat_hdr) - 1;
-
- for (wandev = router_devlist;
- wandev && (cnt < (PROC_BUFSZ - 80));
- wandev = wandev->next) {
- if (!wandev->state) continue;
- cnt += sprintf(&buf[cnt],
- "%-15s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
- wandev->name,
- wandev->station ? " DCE" : " DTE",
- wandev->interface ? " V.35" : " RS-232",
- wandev->clocking ? "internal" : "external",
- wandev->bps,
- wandev->mtu,
- wandev->ndev);
-
- switch (wandev->state) {
-
- case WAN_UNCONFIGURED:
- cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
- break;
-
- case WAN_DISCONNECTED:
- cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
- break;
-
- case WAN_CONNECTING:
- cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
- break;
-
- case WAN_CONNECTED:
- cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
- break;
-
- default:
- cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
- break;
+ /*
+ * 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
+ */
+#ifdef LINUX_2_1
+ 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 pos, offs, len;
+
+ if (count <= 0)
+ return 0;
+
+ dent = inode->u.generic_ip;
+ if ((dent == NULL) || (dent->get_info == NULL))
+ return 0;
+
+ page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
+ if (page == NULL)
+ return -ENOBUFS;
+
+ pos = dent->get_info(page, dent->data, 0, 0, 0);
+ offs = file->f_pos;
+ if (offs < pos) {
+ len = min(pos - offs, count);
+ if(copy_to_user(buf, (page + offs), len))
+ return -EFAULT;
+ file->f_pos += len;
}
+ else
+ len = 0;
+ kfree(page);
+ return len;
}
- return cnt;
-}
-/*
- * Prepare data for reading <device> entry.
- * Return length of data.
- *
- * On entry, the 'start' argument will contain a pointer to WAN device
- * data space.
- */
+#else
+ static int router_proc_read(
+ struct inode* inode, struct file* file, char* buf, int count)
+ {
+ struct proc_dir_entry* dent;
+ char* page;
+ int err, pos, offs, len;
+
+ if (count <= 0)
+ return 0;
+ dent = inode->u.generic_ip;
+ if ((dent == NULL) || (dent->get_info == NULL))
+ return -ENODATA;
+ err = verify_area(VERIFY_WRITE, buf, count);
+ if (err) return err;
+
+ page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
+ if (page == NULL)
+ return -ENOMEM;
+
+ pos = dent->get_info(page, dent->data, 0, 0, 0);
+ offs = file->f_pos;
+ if (offs < pos) {
+ len = min(pos - offs, count);
+ memcpy_tofs((void*)buf, (void*)(page + offs), len);
+ file->f_pos += len;
+ }
+ else len = 0;
+ kfree(page);
+ return len;
+ }
+#endif
-static int wandev_get_info(char* buf, char** start, off_t offs, int len)
-{
- wan_device_t* wandev = (void*)start;
- int cnt = 0;
- int rslt = 0;
- if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
- return 0;
- if (!wandev->state)
- return sprintf(&buf[cnt], "device is not configured!\n");
+ /*
+ * Prepare data for reading 'Config' entry.
+ * Return length of data.
+ */
+
+ static int config_get_info(char* buf, char** start, off_t offs, int len,
+ int dummy)
+ {
+ int cnt = sizeof(conf_hdr) - 1;
+ wan_device_t* wandev;
+ strcpy(buf, conf_hdr);
+ for (wandev = router_devlist;
+ wandev && (cnt < (PROC_BUFSZ - 120));
+ wandev = wandev->next) {
+ if (wandev->state) cnt += sprintf(&buf[cnt],
+ "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
+ wandev->name,
+ wandev->ioport,
+ wandev->irq,
+ wandev->dma,
+ wandev->maddr,
+ wandev->msize,
+ wandev->hw_opt[0],
+ wandev->hw_opt[1],
+ wandev->hw_opt[2],
+ wandev->hw_opt[3]);
+ }
- /* Update device statistics */
- if (wandev->update) {
+ return cnt;
+ }
- rslt = wandev->update(wandev);
- if(rslt) {
- switch (rslt) {
- case -EAGAIN:
- return sprintf(&buf[cnt], "Device is busy!\n");
+ /*
+ * Prepare data for reading 'Status' entry.
+ * Return length of data.
+ */
+
+ static int status_get_info(char* buf, char** start, off_t offs, int len,
+ int dummy)
+ {
+ int cnt = 0;
+ wan_device_t* wandev;
+
+ //cnt += sprintf(&buf[cnt], "\nSTATUS:\n\n");
+ strcpy(&buf[cnt], stat_hdr);
+ cnt += sizeof(stat_hdr) - 1;
+
+ for (wandev = router_devlist;
+ wandev && (cnt < (PROC_BUFSZ - 80));
+ wandev = wandev->next) {
+ if (!wandev->state) continue;
+ cnt += sprintf(&buf[cnt],
+ "%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
+ wandev->name,
+ PROT_DECODE(wandev->config_id),
+ wandev->config_id == WANCONFIG_FR ?
+ (wandev->station ? " Node" : " CPE") :
+ (wandev->config_id == WANCONFIG_X25 ?
+ (wandev->station ? " DCE" : " DTE") :
+ (" N/A")),
+ wandev->interface ? " V.35" : " RS-232",
+ wandev->clocking ? "internal" : "external",
+ wandev->bps,
+ wandev->mtu,
+ wandev->ndev);
+
+ switch (wandev->state) {
+
+ case WAN_UNCONFIGURED:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
+ break;
+
+ case WAN_DISCONNECTED:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
+ break;
+
+ case WAN_CONNECTING:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
+ break;
+
+ case WAN_CONNECTED:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
+ break;
+
+ case WAN_FT1_READY:
+ cnt += sprintf(&buf[cnt], "%-12s\n", "ft1 ready");
+ break;
default:
- return sprintf(&buf[cnt],
- "Device is not configured!\n");
+ cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
+ break;
}
}
+ return cnt;
}
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "total packets received", wandev->stats.rx_packets);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "total packets transmitted", wandev->stats.tx_packets);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "total bytes received", wandev->stats.rx_bytes);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "total bytes transmitted", wandev->stats.tx_bytes);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "bad packets received", wandev->stats.rx_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "packet transmit problems", wandev->stats.tx_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "received frames dropped", wandev->stats.rx_dropped);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "transmit frames dropped", wandev->stats.tx_dropped);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "multicast packets received", wandev->stats.multicast);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "transmit collisions", wandev->stats.collisions);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "receive length errors", wandev->stats.rx_length_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "receiver overrun errors", wandev->stats.rx_over_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "CRC errors", wandev->stats.rx_crc_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "frame format errors (aborts)", wandev->stats.rx_frame_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "receiver fifo overrun", wandev->stats.rx_fifo_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "receiver missed packet", wandev->stats.rx_missed_errors);
- cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
- "aborted frames transmitted", wandev->stats.tx_aborted_errors);
- return cnt;
-}
+ /*
+ * Prepare data for reading <device> entry.
+ * Return length of data.
+ *
+ * On entry, the 'start' argument will contain a pointer to WAN device
+ * data space.
+ */
+
+ static int wandev_get_info(char* buf, char** start, off_t offs, int len,
+ int dummy)
+ {
+ wan_device_t* wandev = (void*)start;
+ int cnt = 0;
+ int rslt = 0;
+
+ if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
+ return 0;
+ if (!wandev->state)
+ return sprintf(&buf[cnt], "Device is not configured!\n");
+
+ /* Update device statistics */
+ if (wandev->update) {
+
+ rslt = wandev->update(wandev);
+ if(rslt) {
+ switch (rslt) {
+ case -EAGAIN:
+ return sprintf(&buf[cnt], "Device is busy!\n");
+
+ default:
+ return sprintf(&buf[cnt],
+ "Device is not configured!\n");
+ }
+ }
+ }
+
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total packets received", wandev->stats.rx_packets);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total packets transmitted", wandev->stats.tx_packets);
+#ifdef LINUX_2_1
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total bytes received", wandev->stats.rx_bytes);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "total bytes transmitted", wandev->stats.tx_bytes);
+#endif
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "bad packets received", wandev->stats.rx_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "packet transmit problems", wandev->stats.tx_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "received frames dropped", wandev->stats.rx_dropped);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "transmit frames dropped", wandev->stats.tx_dropped);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "multicast packets received", wandev->stats.multicast);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "transmit collisions", wandev->stats.collisions);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receive length errors", wandev->stats.rx_length_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receiver overrun errors", wandev->stats.rx_over_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "CRC errors", wandev->stats.rx_crc_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "frame format errors (aborts)", wandev->stats.rx_frame_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receiver fifo overrun", wandev->stats.rx_fifo_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "receiver missed packet", wandev->stats.rx_missed_errors);
+ cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
+ "aborted frames transmitted", wandev->stats.tx_aborted_errors);
+
+ return cnt;
+ }
+
+#endif /* End of ifdef LINUX_2_4 */
+
-/*
- * End
- */
-
#else
/*
* No /proc - output stubs
*/
-
-int __init wanrouter_proc_init(void)
+
+__initfunc(int wanrouter_proc_init(void))
{
return 0;
}
@@ -436,6 +1055,33 @@
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;
+
+ dent = inode->u.generic_ip;
+ if ((dent == NULL) || (dent->data == NULL))
+ return -ENODATA;
+
+ wandev = dent->data;
+
+ printk(KERN_ERR "%s: writing %d bytes to %s...\n",
+ name_root, count, dent->name);
+
+ return 0;
+}
#endif
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)