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