linux/net/wanrouter/wanproc.c
<<
>>
Prefs
   1/*****************************************************************************
   2* wanproc.c     WAN Router Module. /proc filesystem interface.
   3*
   4*               This module is completely hardware-independent and provides
   5*               access to the router using Linux /proc filesystem.
   6*
   7* Author:       Gideon Hack
   8*
   9* Copyright:    (c) 1995-1999 Sangoma Technologies Inc.
  10*
  11*               This program is free software; you can redistribute it and/or
  12*               modify it under the terms of the GNU General Public License
  13*               as published by the Free Software Foundation; either version
  14*               2 of the License, or (at your option) any later version.
  15* ============================================================================
  16* Jun 02, 1999  Gideon Hack     Updates for Linux 2.2.X kernels.
  17* Jun 29, 1997  Alan Cox        Merged with 1.0.3 vendor code
  18* Jan 29, 1997  Gene Kozin      v1.0.1. Implemented /proc read routines
  19* Jan 30, 1997  Alan Cox        Hacked around for 2.1
  20* Dec 13, 1996  Gene Kozin      Initial version (based on Sangoma's WANPIPE)
  21*****************************************************************************/
  22
  23#include <linux/init.h>         /* __initfunc et al. */
  24#include <linux/stddef.h>       /* offsetof(), etc. */
  25#include <linux/errno.h>        /* return codes */
  26#include <linux/kernel.h>
  27#include <linux/module.h>
  28#include <linux/wanrouter.h>    /* WAN router API definitions */
  29#include <linux/seq_file.h>
  30#include <linux/mutex.h>
  31
  32#include <net/net_namespace.h>
  33#include <asm/io.h>
  34
  35#define PROC_STATS_FORMAT "%30s: %12lu\n"
  36
  37/****** Defines and Macros **************************************************/
  38
  39#define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
  40                              (prot == WANCONFIG_X25) ? " X25" : \
  41                                 (prot == WANCONFIG_PPP) ? " PPP" : \
  42                                    (prot == WANCONFIG_CHDLC) ? " CHDLC": \
  43                                       (prot == WANCONFIG_MPPP) ? " MPPP" : \
  44                                           " Unknown" )
  45
  46/****** Function Prototypes *************************************************/
  47
  48#ifdef CONFIG_PROC_FS
  49
  50/* Miscellaneous */
  51
  52/*
  53 *      Structures for interfacing with the /proc filesystem.
  54 *      Router creates its own directory /proc/net/router with the following
  55 *      entries:
  56 *      config          device configuration
  57 *      status          global device statistics
  58 *      <device>        entry for each WAN device
  59 */
  60
  61/*
  62 *      Generic /proc/net/router/<file> file and inode operations
  63 */
  64
  65/*
  66 *      /proc/net/router
  67 */
  68
  69static DEFINE_MUTEX(config_mutex);
  70static struct proc_dir_entry *proc_router;
  71
  72/* Strings */
  73
  74/*
  75 *      Interface functions
  76 */
  77
  78/****** Proc filesystem entry points ****************************************/
  79
  80/*
  81 *      Iterator
  82 */
  83static void *r_start(struct seq_file *m, loff_t *pos)
  84        __acquires(kernel_lock)
  85{
  86        struct wan_device *wandev;
  87        loff_t l = *pos;
  88
  89        mutex_lock(&config_mutex);
  90        if (!l--)
  91                return SEQ_START_TOKEN;
  92        for (wandev = wanrouter_router_devlist; l-- && wandev;
  93             wandev = wandev->next)
  94                ;
  95        return wandev;
  96}
  97
  98static void *r_next(struct seq_file *m, void *v, loff_t *pos)
  99{
 100        struct wan_device *wandev = v;
 101        (*pos)++;
 102        return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
 103}
 104
 105static void r_stop(struct seq_file *m, void *v)
 106        __releases(kernel_lock)
 107{
 108        mutex_unlock(&config_mutex);
 109}
 110
 111static int config_show(struct seq_file *m, void *v)
 112{
 113        struct wan_device *p = v;
 114        if (v == SEQ_START_TOKEN) {
 115                seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |"
 116                            "mem.size|option1|option2|option3|option4\n");
 117                return 0;
 118        }
 119        if (!p->state)
 120                return 0;
 121        seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
 122                        p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
 123                        p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
 124        return 0;
 125}
 126
 127static int status_show(struct seq_file *m, void *v)
 128{
 129        struct wan_device *p = v;
 130        if (v == SEQ_START_TOKEN) {
 131                seq_puts(m, "Device name    |protocol|station|interface|"
 132                            "clocking|baud rate| MTU |ndev|link state\n");
 133                return 0;
 134        }
 135        if (!p->state)
 136                return 0;
 137        seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
 138                p->name,
 139                PROT_DECODE(p->config_id),
 140                p->config_id == WANCONFIG_FR ?
 141                        (p->station ? "Node" : "CPE") :
 142                        (p->config_id == WANCONFIG_X25 ?
 143                        (p->station ? "DCE" : "DTE") :
 144                        ("N/A")),
 145                p->interface ? "V.35" : "RS-232",
 146                p->clocking ? "internal" : "external",
 147                p->bps,
 148                p->mtu,
 149                p->ndev);
 150
 151        switch (p->state) {
 152        case WAN_UNCONFIGURED:
 153                seq_printf(m, "%-12s\n", "unconfigured");
 154                break;
 155        case WAN_DISCONNECTED:
 156                seq_printf(m, "%-12s\n", "disconnected");
 157                break;
 158        case WAN_CONNECTING:
 159                seq_printf(m, "%-12s\n", "connecting");
 160                break;
 161        case WAN_CONNECTED:
 162                seq_printf(m, "%-12s\n", "connected");
 163                break;
 164        default:
 165                seq_printf(m, "%-12s\n", "invalid");
 166                break;
 167        }
 168        return 0;
 169}
 170
 171static const struct seq_operations config_op = {
 172        .start  = r_start,
 173        .next   = r_next,
 174        .stop   = r_stop,
 175        .show   = config_show,
 176};
 177
 178static const struct seq_operations status_op = {
 179        .start  = r_start,
 180        .next   = r_next,
 181        .stop   = r_stop,
 182        .show   = status_show,
 183};
 184
 185static int config_open(struct inode *inode, struct file *file)
 186{
 187        return seq_open(file, &config_op);
 188}
 189
 190static int status_open(struct inode *inode, struct file *file)
 191{
 192        return seq_open(file, &status_op);
 193}
 194
 195static const struct file_operations config_fops = {
 196        .owner   = THIS_MODULE,
 197        .open    = config_open,
 198        .read    = seq_read,
 199        .llseek  = seq_lseek,
 200        .release = seq_release,
 201};
 202
 203static const struct file_operations status_fops = {
 204        .owner   = THIS_MODULE,
 205        .open    = status_open,
 206        .read    = seq_read,
 207        .llseek  = seq_lseek,
 208        .release = seq_release,
 209};
 210
 211static int wandev_show(struct seq_file *m, void *v)
 212{
 213        struct wan_device *wandev = m->private;
 214
 215        if (wandev->magic != ROUTER_MAGIC)
 216                return 0;
 217
 218        if (!wandev->state) {
 219                seq_puts(m, "device is not configured!\n");
 220                return 0;
 221        }
 222
 223        /* Update device statistics */
 224        if (wandev->update) {
 225                int err = wandev->update(wandev);
 226                if (err == -EAGAIN) {
 227                        seq_puts(m, "Device is busy!\n");
 228                        return 0;
 229                }
 230                if (err) {
 231                        seq_puts(m, "Device is not configured!\n");
 232                        return 0;
 233                }
 234        }
 235
 236        seq_printf(m, PROC_STATS_FORMAT,
 237                "total packets received", wandev->stats.rx_packets);
 238        seq_printf(m, PROC_STATS_FORMAT,
 239                "total packets transmitted", wandev->stats.tx_packets);
 240        seq_printf(m, PROC_STATS_FORMAT,
 241                "total bytes received", wandev->stats.rx_bytes);
 242        seq_printf(m, PROC_STATS_FORMAT,
 243                "total bytes transmitted", wandev->stats.tx_bytes);
 244        seq_printf(m, PROC_STATS_FORMAT,
 245                "bad packets received", wandev->stats.rx_errors);
 246        seq_printf(m, PROC_STATS_FORMAT,
 247                "packet transmit problems", wandev->stats.tx_errors);
 248        seq_printf(m, PROC_STATS_FORMAT,
 249                "received frames dropped", wandev->stats.rx_dropped);
 250        seq_printf(m, PROC_STATS_FORMAT,
 251                "transmit frames dropped", wandev->stats.tx_dropped);
 252        seq_printf(m, PROC_STATS_FORMAT,
 253                "multicast packets received", wandev->stats.multicast);
 254        seq_printf(m, PROC_STATS_FORMAT,
 255                "transmit collisions", wandev->stats.collisions);
 256        seq_printf(m, PROC_STATS_FORMAT,
 257                "receive length errors", wandev->stats.rx_length_errors);
 258        seq_printf(m, PROC_STATS_FORMAT,
 259                "receiver overrun errors", wandev->stats.rx_over_errors);
 260        seq_printf(m, PROC_STATS_FORMAT,
 261                "CRC errors", wandev->stats.rx_crc_errors);
 262        seq_printf(m, PROC_STATS_FORMAT,
 263                "frame format errors (aborts)", wandev->stats.rx_frame_errors);
 264        seq_printf(m, PROC_STATS_FORMAT,
 265                "receiver fifo overrun", wandev->stats.rx_fifo_errors);
 266        seq_printf(m, PROC_STATS_FORMAT,
 267                "receiver missed packet", wandev->stats.rx_missed_errors);
 268        seq_printf(m, PROC_STATS_FORMAT,
 269                "aborted frames transmitted", wandev->stats.tx_aborted_errors);
 270        return 0;
 271}
 272
 273static int wandev_open(struct inode *inode, struct file *file)
 274{
 275        return single_open(file, wandev_show, PDE(inode)->data);
 276}
 277
 278static const struct file_operations wandev_fops = {
 279        .owner   = THIS_MODULE,
 280        .open    = wandev_open,
 281        .read    = seq_read,
 282        .llseek  = seq_lseek,
 283        .release = single_release,
 284        .unlocked_ioctl  = wanrouter_ioctl,
 285};
 286
 287/*
 288 *      Initialize router proc interface.
 289 */
 290
 291int __init wanrouter_proc_init(void)
 292{
 293        struct proc_dir_entry *p;
 294        proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
 295        if (!proc_router)
 296                goto fail;
 297
 298        p = proc_create("config", S_IRUGO, proc_router, &config_fops);
 299        if (!p)
 300                goto fail_config;
 301        p = proc_create("status", S_IRUGO, proc_router, &status_fops);
 302        if (!p)
 303                goto fail_stat;
 304        return 0;
 305fail_stat:
 306        remove_proc_entry("config", proc_router);
 307fail_config:
 308        remove_proc_entry(ROUTER_NAME, init_net.proc_net);
 309fail:
 310        return -ENOMEM;
 311}
 312
 313/*
 314 *      Clean up router proc interface.
 315 */
 316
 317void wanrouter_proc_cleanup(void)
 318{
 319        remove_proc_entry("config", proc_router);
 320        remove_proc_entry("status", proc_router);
 321        remove_proc_entry(ROUTER_NAME, init_net.proc_net);
 322}
 323
 324/*
 325 *      Add directory entry for WAN device.
 326 */
 327
 328int wanrouter_proc_add(struct wan_device* wandev)
 329{
 330        if (wandev->magic != ROUTER_MAGIC)
 331                return -EINVAL;
 332
 333        wandev->dent = proc_create(wandev->name, S_IRUGO,
 334                                   proc_router, &wandev_fops);
 335        if (!wandev->dent)
 336                return -ENOMEM;
 337        wandev->dent->data      = wandev;
 338        return 0;
 339}
 340
 341/*
 342 *      Delete directory entry for WAN device.
 343 */
 344int wanrouter_proc_delete(struct wan_device* wandev)
 345{
 346        if (wandev->magic != ROUTER_MAGIC)
 347                return -EINVAL;
 348        remove_proc_entry(wandev->name, proc_router);
 349        return 0;
 350}
 351
 352#else
 353
 354/*
 355 *      No /proc - output stubs
 356 */
 357
 358int __init wanrouter_proc_init(void)
 359{
 360        return 0;
 361}
 362
 363void wanrouter_proc_cleanup(void)
 364{
 365}
 366
 367int wanrouter_proc_add(struct wan_device *wandev)
 368{
 369        return 0;
 370}
 371
 372int wanrouter_proc_delete(struct wan_device *wandev)
 373{
 374        return 0;
 375}
 376
 377#endif
 378
 379/*
 380 *      End
 381 */
 382
 383