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