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/smp_lock.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 folowing
  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 struct proc_dir_entry *proc_router;
  70
  71/* Strings */
  72
  73/*
  74 *      Interface functions
  75 */
  76
  77/****** Proc filesystem entry points ****************************************/
  78
  79/*
  80 *      Iterator
  81 */
  82static void *r_start(struct seq_file *m, loff_t *pos)
  83{
  84        struct wan_device *wandev;
  85        loff_t l = *pos;
  86
  87        lock_kernel();
  88        if (!l--)
  89                return SEQ_START_TOKEN;
  90        for (wandev = wanrouter_router_devlist; l-- && wandev;
  91             wandev = wandev->next)
  92                ;
  93        return wandev;
  94}
  95
  96static void *r_next(struct seq_file *m, void *v, loff_t *pos)
  97{
  98        struct wan_device *wandev = v;
  99        (*pos)++;
 100        return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
 101}
 102
 103static void r_stop(struct seq_file *m, void *v)
 104{
 105        unlock_kernel();
 106}
 107
 108static int config_show(struct seq_file *m, void *v)
 109{
 110        struct wan_device *p = v;
 111        if (v == SEQ_START_TOKEN) {
 112                seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |"
 113                            "mem.size|option1|option2|option3|option4\n");
 114                return 0;
 115        }
 116        if (!p->state)
 117                return 0;
 118        seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
 119                        p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
 120                        p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
 121        return 0;
 122}
 123
 124static int status_show(struct seq_file *m, void *v)
 125{
 126        struct wan_device *p = v;
 127        if (v == SEQ_START_TOKEN) {
 128                seq_puts(m, "Device name    |protocol|station|interface|"
 129                            "clocking|baud rate| MTU |ndev|link state\n");
 130                return 0;
 131        }
 132        if (!p->state)
 133                return 0;
 134        seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
 135                p->name,
 136                PROT_DECODE(p->config_id),
 137                p->config_id == WANCONFIG_FR ?
 138                        (p->station ? "Node" : "CPE") :
 139                        (p->config_id == WANCONFIG_X25 ?
 140                        (p->station ? "DCE" : "DTE") :
 141                        ("N/A")),
 142                p->interface ? "V.35" : "RS-232",
 143                p->clocking ? "internal" : "external",
 144                p->bps,
 145                p->mtu,
 146                p->ndev);
 147
 148        switch (p->state) {
 149        case WAN_UNCONFIGURED:
 150                seq_printf(m, "%-12s\n", "unconfigured");
 151                break;
 152        case WAN_DISCONNECTED:
 153                seq_printf(m, "%-12s\n", "disconnected");
 154                break;
 155        case WAN_CONNECTING:
 156                seq_printf(m, "%-12s\n", "connecting");
 157                break;
 158        case WAN_CONNECTED:
 159                seq_printf(m, "%-12s\n", "connected");
 160                break;
 161        default:
 162                seq_printf(m, "%-12s\n", "invalid");
 163                break;
 164        }
 165        return 0;
 166}
 167
 168static const struct seq_operations config_op = {
 169        .start  = r_start,
 170        .next   = r_next,
 171        .stop   = r_stop,
 172        .show   = config_show,
 173};
 174
 175static const struct seq_operations status_op = {
 176        .start  = r_start,
 177        .next   = r_next,
 178        .stop   = r_stop,
 179        .show   = status_show,
 180};
 181
 182static int config_open(struct inode *inode, struct file *file)
 183{
 184        return seq_open(file, &config_op);
 185}
 186
 187static int status_open(struct inode *inode, struct file *file)
 188{
 189        return seq_open(file, &status_op);
 190}
 191
 192static const struct file_operations config_fops = {
 193        .owner   = THIS_MODULE,
 194        .open    = config_open,
 195        .read    = seq_read,
 196        .llseek  = seq_lseek,
 197        .release = seq_release,
 198};
 199
 200static const struct file_operations status_fops = {
 201        .owner   = THIS_MODULE,
 202        .open    = status_open,
 203        .read    = seq_read,
 204        .llseek  = seq_lseek,
 205        .release = seq_release,
 206};
 207
 208static int wandev_show(struct seq_file *m, void *v)
 209{
 210        struct wan_device *wandev = m->private;
 211
 212        if (wandev->magic != ROUTER_MAGIC)
 213                return 0;
 214
 215        if (!wandev->state) {
 216                seq_puts(m, "device is not configured!\n");
 217                return 0;
 218        }
 219
 220        /* Update device statistics */
 221        if (wandev->update) {
 222                int err = wandev->update(wandev);
 223                if (err == -EAGAIN) {
 224                        seq_puts(m, "Device is busy!\n");
 225                        return 0;
 226                }
 227                if (err) {
 228                        seq_puts(m, "Device is not configured!\n");
 229                        return 0;
 230                }
 231        }
 232
 233        seq_printf(m, PROC_STATS_FORMAT,
 234                "total packets received", wandev->stats.rx_packets);
 235        seq_printf(m, PROC_STATS_FORMAT,
 236                "total packets transmitted", wandev->stats.tx_packets);
 237        seq_printf(m, PROC_STATS_FORMAT,
 238                "total bytes received", wandev->stats.rx_bytes);
 239        seq_printf(m, PROC_STATS_FORMAT,
 240                "total bytes transmitted", wandev->stats.tx_bytes);
 241        seq_printf(m, PROC_STATS_FORMAT,
 242                "bad packets received", wandev->stats.rx_errors);
 243        seq_printf(m, PROC_STATS_FORMAT,
 244                "packet transmit problems", wandev->stats.tx_errors);
 245        seq_printf(m, PROC_STATS_FORMAT,
 246                "received frames dropped", wandev->stats.rx_dropped);
 247        seq_printf(m, PROC_STATS_FORMAT,
 248                "transmit frames dropped", wandev->stats.tx_dropped);
 249        seq_printf(m, PROC_STATS_FORMAT,
 250                "multicast packets received", wandev->stats.multicast);
 251        seq_printf(m, PROC_STATS_FORMAT,
 252                "transmit collisions", wandev->stats.collisions);
 253        seq_printf(m, PROC_STATS_FORMAT,
 254                "receive length errors", wandev->stats.rx_length_errors);
 255        seq_printf(m, PROC_STATS_FORMAT,
 256                "receiver overrun errors", wandev->stats.rx_over_errors);
 257        seq_printf(m, PROC_STATS_FORMAT,
 258                "CRC errors", wandev->stats.rx_crc_errors);
 259        seq_printf(m, PROC_STATS_FORMAT,
 260                "frame format errors (aborts)", wandev->stats.rx_frame_errors);
 261        seq_printf(m, PROC_STATS_FORMAT,
 262                "receiver fifo overrun", wandev->stats.rx_fifo_errors);
 263        seq_printf(m, PROC_STATS_FORMAT,
 264                "receiver missed packet", wandev->stats.rx_missed_errors);
 265        seq_printf(m, PROC_STATS_FORMAT,
 266                "aborted frames transmitted", wandev->stats.tx_aborted_errors);
 267        return 0;
 268}
 269
 270static int wandev_open(struct inode *inode, struct file *file)
 271{
 272        return single_open(file, wandev_show, PDE(inode)->data);
 273}
 274
 275static const struct file_operations wandev_fops = {
 276        .owner   = THIS_MODULE,
 277        .open    = wandev_open,
 278        .read    = seq_read,
 279        .llseek  = seq_lseek,
 280        .release = single_release,
 281        .unlocked_ioctl  = wanrouter_ioctl,
 282};
 283
 284/*
 285 *      Initialize router proc interface.
 286 */
 287
 288int __init wanrouter_proc_init(void)
 289{
 290        struct proc_dir_entry *p;
 291        proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
 292        if (!proc_router)
 293                goto fail;
 294
 295        p = proc_create("config", S_IRUGO, proc_router, &config_fops);
 296        if (!p)
 297                goto fail_config;
 298        p = proc_create("status", S_IRUGO, proc_router, &status_fops);
 299        if (!p)
 300                goto fail_stat;
 301        return 0;
 302fail_stat:
 303        remove_proc_entry("config", proc_router);
 304fail_config:
 305        remove_proc_entry(ROUTER_NAME, init_net.proc_net);
 306fail:
 307        return -ENOMEM;
 308}
 309
 310/*
 311 *      Clean up router proc interface.
 312 */
 313
 314void wanrouter_proc_cleanup(void)
 315{
 316        remove_proc_entry("config", proc_router);
 317        remove_proc_entry("status", proc_router);
 318        remove_proc_entry(ROUTER_NAME, init_net.proc_net);
 319}
 320
 321/*
 322 *      Add directory entry for WAN device.
 323 */
 324
 325int wanrouter_proc_add(struct wan_device* wandev)
 326{
 327        if (wandev->magic != ROUTER_MAGIC)
 328                return -EINVAL;
 329
 330        wandev->dent = proc_create(wandev->name, S_IRUGO,
 331                                   proc_router, &wandev_fops);
 332        if (!wandev->dent)
 333                return -ENOMEM;
 334        wandev->dent->data      = wandev;
 335        return 0;
 336}
 337
 338/*
 339 *      Delete directory entry for WAN device.
 340 */
 341int wanrouter_proc_delete(struct wan_device* wandev)
 342{
 343        if (wandev->magic != ROUTER_MAGIC)
 344                return -EINVAL;
 345        remove_proc_entry(wandev->name, proc_router);
 346        return 0;
 347}
 348
 349#else
 350
 351/*
 352 *      No /proc - output stubs
 353 */
 354
 355int __init wanrouter_proc_init(void)
 356{
 357        return 0;
 358}
 359
 360void wanrouter_proc_cleanup(void)
 361{
 362}
 363
 364int wanrouter_proc_add(struct wan_device *wandev)
 365{
 366        return 0;
 367}
 368
 369int wanrouter_proc_delete(struct wan_device *wandev)
 370{
 371        return 0;
 372}
 373
 374#endif
 375
 376/*
 377 *      End
 378 */
 379
 380