linux-old/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/version.h>
  24#include <linux/config.h>
  25#include <linux/stddef.h>       /* offsetof(), etc. */
  26#include <linux/errno.h>        /* return codes */
  27#include <linux/kernel.h>
  28#include <linux/slab.h> /* kmalloc(), kfree() */
  29#include <linux/mm.h>           /* verify_area(), etc. */
  30#include <linux/string.h>       /* inline mem*, str* functions */
  31#include <asm/byteorder.h>      /* htons(), etc. */
  32#include <asm/io.h>
  33#include <linux/wanrouter.h>    /* WAN router API definitions */
  34
  35
  36
  37#if defined(LINUX_2_1) || defined(LINUX_2_4) 
  38 #include <linux/init.h>        /* __initfunc et al. */
  39 #include <asm/uaccess.h>       /* copy_to_user */
  40 #define PROC_STATS_FORMAT "%30s: %12lu\n"
  41#else
  42 #define PROC_STATS_FORMAT "%30s: %12u\n"
  43 #include <asm/segment.h>       /* kernel <-> user copy */
  44#endif
  45
  46
  47/****** Defines and Macros **************************************************/
  48
  49#define PROC_BUFSZ      4000    /* buffer size for printing proc info */
  50
  51#define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
  52                              (prot == WANCONFIG_X25) ? " X25" : \
  53                                 (prot == WANCONFIG_PPP) ? " PPP" : \
  54                                    (prot == WANCONFIG_CHDLC) ? " CHDLC": \
  55                                       (prot == WANCONFIG_MPPP) ? " MPPP" : \
  56                                           " Unknown" )
  57        
  58/****** Data Types **********************************************************/
  59
  60typedef struct wan_stat_entry
  61{
  62        struct wan_stat_entry *next;
  63        char *description;              /* description string */
  64        void *data;                     /* -> data */
  65        unsigned data_type;             /* data type */
  66} wan_stat_entry_t;
  67
  68/****** Function Prototypes *************************************************/
  69
  70#ifdef CONFIG_PROC_FS
  71
  72
  73#ifdef LINUX_2_4  /* Start of LINUX 2.4.X code */
  74
  75
  76        /* Proc filesystem interface */
  77        static int router_proc_perms(struct inode *, int);
  78        static ssize_t router_proc_read(struct file* file, char* buf, size_t count,                                     loff_t *ppos);
  79
  80        /* Methods for preparing data for reading proc entries */
  81
  82        static int config_get_info(char* buf, char** start, off_t offs, int len);
  83        static int status_get_info(char* buf, char** start, off_t offs, int len);
  84        static int wandev_get_info(char* buf, char** start, off_t offs, int len);
  85
  86        /* Miscellaneous */
  87
  88        /*
  89         *      Structures for interfacing with the /proc filesystem.
  90         *      Router creates its own directory /proc/net/router with the folowing
  91         *      entries:
  92         *      config          device configuration
  93         *      status          global device statistics
  94         *      <device>        entry for each WAN device
  95         */
  96
  97        /*
  98         *      Generic /proc/net/router/<file> file and inode operations 
  99         */
 100        static struct file_operations router_fops =
 101        {
 102                read:           router_proc_read,
 103        };
 104
 105        static struct inode_operations router_inode =
 106        {
 107                permission:     router_proc_perms,
 108        };
 109
 110        /*
 111         *      /proc/net/router/<device> file operations
 112         */
 113
 114        static struct file_operations wandev_fops =
 115        {
 116                read:           router_proc_read,
 117                ioctl:          wanrouter_ioctl,
 118        };
 119
 120        /*
 121         *      /proc/net/router 
 122         */
 123
 124        static struct proc_dir_entry *proc_router;
 125
 126        /* Strings */
 127        static char conf_hdr[] =
 128                "Device name    | port |IRQ|DMA|  mem.addr  |mem.size|"
 129                "option1|option2|option3|option4\n";
 130                
 131        static char stat_hdr[] =
 132                "Device name    |protocol|station|interface|clocking|baud rate"
 133                "| MTU |ndev|link state\n";
 134
 135
 136        /*
 137         *      Interface functions
 138         */
 139
 140        /*
 141         *      Initialize router proc interface.
 142         */
 143
 144        int __init wanrouter_proc_init (void)
 145        {
 146                struct proc_dir_entry *p;
 147                proc_router = proc_mkdir(ROUTER_NAME, proc_net);
 148                if (!proc_router)
 149                        goto fail;
 150
 151                p = create_proc_entry("config",0,proc_router);
 152                if (!p)
 153                        goto fail_config;
 154                p->proc_fops = &router_fops;
 155                p->proc_iops = &router_inode;
 156                p->get_info = config_get_info;
 157                p = create_proc_entry("status",0,proc_router);
 158                if (!p)
 159                        goto fail_stat;
 160                p->proc_fops = &router_fops;
 161                p->proc_iops = &router_inode;
 162                p->get_info = status_get_info;
 163                return 0;
 164        fail_stat:
 165                remove_proc_entry("config", proc_router);
 166        fail_config:
 167                remove_proc_entry(ROUTER_NAME, proc_net);
 168        fail:
 169                return -ENOMEM;
 170        }
 171
 172        /*
 173         *      Clean up router proc interface.
 174         */
 175
 176        void wanrouter_proc_cleanup (void)
 177        {
 178                remove_proc_entry("config", proc_router);
 179                remove_proc_entry("status", proc_router);
 180                remove_proc_entry(ROUTER_NAME,proc_net);
 181        }
 182
 183        /*
 184         *      Add directory entry for WAN device.
 185         */
 186
 187        int wanrouter_proc_add (wan_device_t* wandev)
 188        {
 189                if (wandev->magic != ROUTER_MAGIC)
 190                        return -EINVAL;
 191                        
 192                wandev->dent = create_proc_entry(wandev->name, 0, proc_router);
 193                if (!wandev->dent)
 194                        return -ENOMEM;
 195                wandev->dent->proc_fops = &wandev_fops;
 196                wandev->dent->proc_iops = &router_inode;
 197                wandev->dent->get_info  = wandev_get_info;
 198                wandev->dent->data      = wandev;
 199                return 0;
 200        }
 201
 202        /*
 203         *      Delete directory entry for WAN device.
 204         */
 205         
 206        int wanrouter_proc_delete(wan_device_t* wandev)
 207        {
 208                if (wandev->magic != ROUTER_MAGIC)
 209                        return -EINVAL;
 210                remove_proc_entry(wandev->name, proc_router);
 211                return 0;
 212        }
 213
 214        /****** Proc filesystem entry points ****************************************/
 215
 216        /*
 217         *      Verify access rights.
 218         */
 219
 220        static int router_proc_perms (struct inode* inode, int op)
 221        {
 222                return 0;
 223        }
 224
 225        /*
 226         *      Read router proc directory entry.
 227         *      This is universal routine for reading all entries in /proc/net/wanrouter
 228         *      directory.  Each directory entry contains a pointer to the 'method' for
 229         *      preparing data for that entry.
 230         *      o verify arguments
 231         *      o allocate kernel buffer
 232         *      o call get_info() to prepare data
 233         *      o copy data to user space
 234         *      o release kernel buffer
 235         *
 236         *      Return: number of bytes copied to user space (0, if no data)
 237         *              <0      error
 238         */
 239
 240        static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
 241                                        loff_t *ppos)
 242        {
 243                struct inode *inode = file->f_dentry->d_inode;
 244                struct proc_dir_entry* dent;
 245                char* page;
 246                int pos, len;
 247                loff_t n = *ppos;
 248                unsigned offs = n;
 249
 250                if (count <= 0)
 251                        return 0;
 252                        
 253                dent = inode->u.generic_ip;
 254                if ((dent == NULL) || (dent->get_info == NULL))
 255                        return 0;
 256                        
 257                page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
 258                if (page == NULL)
 259                        return -ENOBUFS;
 260                        
 261                pos = dent->get_info(page, dent->data, 0, 0);
 262                if (offs == n && offs < pos) {
 263                        len = min_t(unsigned int, pos - offs, count);
 264                        if (copy_to_user(buf, (page + offs), len)) {
 265                                kfree(page);
 266                                return -EFAULT;
 267                        }
 268                        *ppos = offs + len;
 269                }
 270                else
 271                        len = 0;
 272                kfree(page);
 273                return len;
 274        }
 275
 276        /*
 277         *      Prepare data for reading 'Config' entry.
 278         *      Return length of data.
 279         */
 280
 281        static int config_get_info(char* buf, char** start, off_t offs, int len)
 282        {
 283                int cnt = sizeof(conf_hdr) - 1;
 284                wan_device_t* wandev;
 285                strcpy(buf, conf_hdr);
 286                for (wandev = router_devlist;
 287                     wandev && (cnt < (PROC_BUFSZ - 120));
 288                     wandev = wandev->next) {
 289                        if (wandev->state) cnt += sprintf(&buf[cnt],
 290                                "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
 291                                wandev->name,
 292                                wandev->ioport,
 293                                wandev->irq,
 294                                wandev->dma,
 295                                wandev->maddr,
 296                                wandev->msize,
 297                                wandev->hw_opt[0],
 298                                wandev->hw_opt[1],
 299                                wandev->hw_opt[2],
 300                                wandev->hw_opt[3]);
 301                }
 302
 303                return cnt;
 304        }
 305
 306        /*
 307         *      Prepare data for reading 'Status' entry.
 308         *      Return length of data.
 309         */
 310
 311        static int status_get_info(char* buf, char** start, off_t offs, int len)
 312        {
 313                int cnt = 0;
 314                wan_device_t* wandev;
 315
 316                //cnt += sprintf(&buf[cnt], "\nSTATUS:\n\n");
 317                strcpy(&buf[cnt], stat_hdr);
 318                cnt += sizeof(stat_hdr) - 1;
 319
 320                for (wandev = router_devlist;
 321                     wandev && (cnt < (PROC_BUFSZ - 80));
 322                     wandev = wandev->next) {
 323                        if (!wandev->state) continue;
 324                        cnt += sprintf(&buf[cnt],
 325                                "%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
 326                                wandev->name,
 327                                PROT_DECODE(wandev->config_id),
 328                                wandev->config_id == WANCONFIG_FR ? 
 329                                        (wandev->station ? " Node" : " CPE") :
 330                                        (wandev->config_id == WANCONFIG_X25 ?
 331                                        (wandev->station ? " DCE" : " DTE") :
 332                                        (" N/A")),
 333                                wandev->interface ? " V.35" : " RS-232",
 334                                wandev->clocking ? "internal" : "external",
 335                                wandev->bps,
 336                                wandev->mtu,
 337                                wandev->ndev);
 338
 339                        switch (wandev->state) {
 340
 341                        case WAN_UNCONFIGURED:
 342                                cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
 343                                break;
 344
 345                        case WAN_DISCONNECTED:
 346                                cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
 347                                break;
 348
 349                        case WAN_CONNECTING:
 350                                cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
 351                                break;
 352
 353                        case WAN_CONNECTED:
 354                                cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
 355                                break;
 356
 357                        default:
 358                                cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
 359                                break;
 360                        }
 361                }
 362                return cnt;
 363        }
 364
 365        /*
 366         *      Prepare data for reading <device> entry.
 367         *      Return length of data.
 368         *
 369         *      On entry, the 'start' argument will contain a pointer to WAN device
 370         *      data space.
 371         */
 372
 373        static int wandev_get_info(char* buf, char** start, off_t offs, int len)
 374        {
 375                wan_device_t* wandev = (void*)start;
 376                int cnt = 0;
 377                int rslt = 0;
 378
 379                if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
 380                        return 0;
 381                if (!wandev->state)
 382                        return sprintf(&buf[cnt], "device is not configured!\n");
 383
 384                /* Update device statistics */
 385                if (wandev->update) {
 386
 387                        rslt = wandev->update(wandev);
 388                        if(rslt) {
 389                                switch (rslt) {
 390                                case -EAGAIN:
 391                                        return sprintf(&buf[cnt], "Device is busy!\n");
 392
 393                                default:
 394                                        return sprintf(&buf[cnt],
 395                                                "Device is not configured!\n");
 396                                }
 397                        }
 398                }
 399
 400                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 401                        "total packets received", wandev->stats.rx_packets);
 402                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 403                        "total packets transmitted", wandev->stats.tx_packets);
 404                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 405                        "total bytes received", wandev->stats.rx_bytes);
 406                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 407                        "total bytes transmitted", wandev->stats.tx_bytes);
 408                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 409                        "bad packets received", wandev->stats.rx_errors);
 410                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 411                        "packet transmit problems", wandev->stats.tx_errors);
 412                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 413                        "received frames dropped", wandev->stats.rx_dropped);
 414                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 415                        "transmit frames dropped", wandev->stats.tx_dropped);
 416                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 417                        "multicast packets received", wandev->stats.multicast);
 418                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 419                        "transmit collisions", wandev->stats.collisions);
 420                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 421                        "receive length errors", wandev->stats.rx_length_errors);
 422                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 423                        "receiver overrun errors", wandev->stats.rx_over_errors);
 424                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 425                        "CRC errors", wandev->stats.rx_crc_errors);
 426                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 427                        "frame format errors (aborts)", wandev->stats.rx_frame_errors);
 428                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 429                        "receiver fifo overrun", wandev->stats.rx_fifo_errors);
 430                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 431                        "receiver missed packet", wandev->stats.rx_missed_errors);
 432                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 433                        "aborted frames transmitted", wandev->stats.tx_aborted_errors);
 434                return cnt;
 435        }
 436
 437
 438#else /* ------------------- END OF LINUX 2.4.X VERSION -------------*/
 439
 440
 441
 442        /* Proc filesystem interface */
 443        static int router_proc_perms(struct inode *, int);
 444#ifdef LINUX_2_1
 445        static ssize_t router_proc_read(struct file *file, char *buf, size_t count,                                     loff_t *ppos);
 446#else
 447        static int router_proc_read(
 448                struct inode* inode, struct file* file, char* buf, int count);
 449        static int device_write(
 450                struct inode* inode, struct file* file, const char* buf, int count);
 451#endif
 452
 453        /* Methods for preparing data for reading proc entries */
 454        static int config_get_info(char* buf, char** start, off_t offs, int len,
 455                int dummy);
 456        static int status_get_info(char* buf, char** start, off_t offs, int len,
 457                int dummy);
 458        static int wandev_get_info(char* buf, char** start, off_t offs, int len,
 459                int dummy);
 460
 461        /* Miscellaneous */
 462
 463        /*
 464         *      Global Data
 465         */
 466
 467        /*
 468         *      Names of the proc directory entries 
 469         */
 470
 471        static char name_root[] = ROUTER_NAME;
 472        static char name_conf[] = "config";
 473        static char name_stat[] = "status";
 474
 475        /*
 476         *      Structures for interfacing with the /proc filesystem.
 477         *      Router creates its own directory /proc/net/router with the folowing
 478         *      entries:
 479         *      config          device configuration
 480         *      status          global device statistics
 481         *      <device>        entry for each WAN device
 482         */
 483
 484        /*
 485         *      Generic /proc/net/router/<file> file and inode operations 
 486         */
 487#ifdef LINUX_2_1
 488        static struct file_operations router_fops =
 489        {
 490                NULL,                   /* lseek   */
 491                router_proc_read,       /* read    */
 492                NULL,                   /* write   */
 493                NULL,                   /* readdir */
 494                NULL,                   /* select  */
 495                NULL,                   /* ioctl   */
 496                NULL,                   /* mmap    */
 497                NULL,                   /* no special open code    */
 498                NULL,                   /* flush */
 499                NULL,                   /* no special release code */
 500                NULL                    /* can't fsync */
 501        };
 502#else
 503        static struct file_operations router_fops =
 504        {
 505                NULL,                   /* lseek   */
 506                router_proc_read,       /* read    */
 507                NULL,                   /* write   */
 508                NULL,                   /* readdir */
 509                NULL,                   /* select  */
 510                NULL,                   /* ioctl   */
 511                NULL,                   /* mmap    */
 512                NULL,                   /* no special open code    */
 513                NULL,                   /* no special release code */
 514                NULL                    /* can't fsync */
 515        };
 516#endif
 517
 518        static struct inode_operations router_inode =
 519        {
 520                &router_fops,
 521                NULL,                   /* create */
 522                NULL,                   /* lookup */
 523                NULL,                   /* link */
 524                NULL,                   /* unlink */
 525                NULL,                   /* symlink */
 526                NULL,                   /* mkdir */
 527                NULL,                   /* rmdir */
 528                NULL,                   /* mknod */
 529                NULL,                   /* rename */
 530                NULL,                   /* follow link */
 531                NULL,                   /* readlink */
 532                NULL,                   /* readpage */
 533                NULL,                   /* writepage */
 534                NULL,                   /* bmap */
 535                NULL,                   /* truncate */
 536                router_proc_perms
 537        };
 538
 539        /*
 540         *      /proc/net/router/<device> file and inode operations
 541         */
 542
 543#ifdef LINUX_2_1
 544        static struct file_operations wandev_fops =
 545        {
 546                NULL,                   /* lseek   */
 547                router_proc_read,       /* read    */
 548                NULL,                   /* write   */
 549                NULL,                   /* readdir */
 550                NULL,                   /* select  */
 551                wanrouter_ioctl,        /* ioctl   */
 552                NULL,                   /* mmap    */
 553                NULL,                   /* no special open code    */
 554                NULL,                   /* flush */
 555                NULL,                   /* no special release code */
 556                NULL                    /* can't fsync */
 557        };
 558#else
 559        static struct file_operations wandev_fops =
 560        {
 561                NULL,                   /* lseek   */
 562                router_proc_read,       /* read    */
 563                device_write,           /* write   */
 564                NULL,                   /* readdir */
 565                NULL,                   /* select  */
 566                wanrouter_ioctl,        /* ioctl   */
 567                NULL,                   /* mmap    */
 568                NULL,                   /* no special open code    */
 569                NULL,                   /* no special release code */
 570                NULL                    /* can't fsync */
 571        };
 572#endif
 573
 574        static struct inode_operations wandev_inode =
 575        {
 576                &wandev_fops,
 577                NULL,                   /* create */
 578                NULL,                   /* lookup */
 579                NULL,                   /* link */
 580                NULL,                   /* unlink */
 581                NULL,                   /* symlink */
 582                NULL,                   /* mkdir */
 583                NULL,                   /* rmdir */
 584                NULL,                   /* mknod */
 585                NULL,                   /* rename */
 586                NULL,                   /* readlink */
 587                NULL,                   /* follow_link */
 588                NULL,                   /* readpage */
 589                NULL,                   /* writepage */
 590                NULL,                   /* bmap */
 591                NULL,                   /* truncate */
 592                router_proc_perms
 593        };
 594
 595        /*
 596         * Proc filesystem derectory entries.
 597         */
 598
 599        /*
 600         *      /proc/net/router 
 601         */
 602         
 603        static struct proc_dir_entry proc_router =
 604        {
 605                0,                      /* .low_ino */
 606                sizeof(name_root) - 1,  /* .namelen */
 607                name_root,              /* .name */
 608                0555 | S_IFDIR,         /* .mode */
 609                2,                      /* .nlink */
 610                0,                      /* .uid */
 611                0,                      /* .gid */
 612                0,                      /* .size */
 613                &proc_dir_inode_operations, /* .ops */
 614                NULL,                   /* .get_info */
 615                NULL,                   /* .fill_node */
 616                NULL,                   /* .next */
 617                NULL,                   /* .parent */
 618                NULL,                   /* .subdir */
 619                NULL,                   /* .data */
 620        };
 621
 622        /*
 623         *      /proc/net/router/config 
 624         */
 625         
 626        static struct proc_dir_entry proc_router_conf =
 627        {
 628                0,                      /* .low_ino */
 629                sizeof(name_conf) - 1,  /* .namelen */
 630                name_conf,              /* .name */
 631                0444 | S_IFREG,         /* .mode */
 632                1,                      /* .nlink */
 633                0,                      /* .uid */
 634                0,                      /* .gid */
 635                0,                      /* .size */
 636                &router_inode,          /* .ops */
 637                &config_get_info,       /* .get_info */
 638                NULL,                   /* .fill_node */
 639                NULL,                   /* .next */
 640                NULL,                   /* .parent */
 641                NULL,                   /* .subdir */
 642                NULL,                   /* .data */
 643        };
 644
 645        /*
 646         *      /proc/net/router/status 
 647         */
 648         
 649        static struct proc_dir_entry proc_router_stat =
 650        {
 651                0,                      /* .low_ino */
 652                sizeof(name_stat) - 1,  /* .namelen */
 653                name_stat,              /* .name */
 654                0444 | S_IFREG,         /* .mode */
 655                1,                      /* .nlink */
 656                0,                      /* .uid */
 657                0,                      /* .gid */
 658                0,                      /* .size */
 659                &router_inode,          /* .ops */
 660                status_get_info,        /* .get_info */
 661                NULL,                   /* .fill_node */
 662                NULL,                   /* .next */
 663                NULL,                   /* .parent */
 664                NULL,                   /* .subdir */
 665                NULL,                   /* .data */
 666        };
 667
 668        /* Strings */
 669        static char conf_hdr[] =
 670                "Device name    | port |IRQ|DMA|  mem.addr  |mem.size|"
 671                "option1|option2|option3|option4\n";
 672                
 673        static char stat_hdr[] =
 674                "Device name    |protocol|station|interface|clocking|baud rate| MTU |ndev"
 675                "|link state\n";
 676
 677
 678        /*
 679         *      Interface functions
 680         */
 681
 682        /*
 683         *      Initialize router proc interface.
 684         */
 685
 686#ifdef LINUX_2_1
 687        __initfunc(int wanrouter_proc_init (void))
 688        {
 689                int err = proc_register(proc_net, &proc_router);
 690
 691                if (!err) {
 692                        proc_register(&proc_router, &proc_router_conf);
 693                        proc_register(&proc_router, &proc_router_stat);
 694                }
 695                return err;
 696        }
 697#else
 698        int wanrouter_proc_init (void)
 699        {
 700                int err = proc_register_dynamic(&proc_net, &proc_router);
 701
 702                if (!err) {
 703                        proc_register_dynamic(&proc_router, &proc_router_conf);
 704                        proc_register_dynamic(&proc_router, &proc_router_stat);
 705                }
 706                return err;
 707        }
 708#endif
 709
 710        /*
 711         *      Clean up router proc interface.
 712         */
 713
 714        void wanrouter_proc_cleanup (void)
 715        {
 716                proc_unregister(&proc_router, proc_router_conf.low_ino);
 717                proc_unregister(&proc_router, proc_router_stat.low_ino);
 718#ifdef LINUX_2_1
 719                proc_unregister(proc_net, proc_router.low_ino);
 720#else
 721                proc_unregister(&proc_net, proc_router.low_ino);
 722#endif
 723        }
 724
 725        /*
 726         *      Add directory entry for WAN device.
 727         */
 728
 729        int wanrouter_proc_add (wan_device_t* wandev)
 730        {
 731                if (wandev->magic != ROUTER_MAGIC)
 732                        return -EINVAL;
 733                
 734                memset(&wandev->dent, 0, sizeof(wandev->dent));
 735                wandev->dent.namelen    = strlen(wandev->name);
 736                wandev->dent.name       = wandev->name;
 737                wandev->dent.mode       = 0444 | S_IFREG;
 738                wandev->dent.nlink      = 1;
 739                wandev->dent.ops        = &wandev_inode;
 740                wandev->dent.get_info   = &wandev_get_info;
 741                wandev->dent.data       = wandev;
 742#ifdef LINUX_2_1
 743                return proc_register(&proc_router, &wandev->dent);
 744#else
 745                return proc_register_dynamic(&proc_router, &wandev->dent);
 746#endif
 747        }
 748
 749        /*
 750         *      Delete directory entry for WAN device.
 751         */
 752         
 753        int wanrouter_proc_delete(wan_device_t* wandev)
 754        {
 755                if (wandev->magic != ROUTER_MAGIC)
 756                        return -EINVAL;
 757                proc_unregister(&proc_router, wandev->dent.low_ino);
 758                return 0;
 759        }
 760
 761        /****** Proc filesystem entry points ****************************************/
 762
 763        /*
 764         *      Verify access rights.
 765         */
 766
 767        static int router_proc_perms (struct inode* inode, int op)
 768        {
 769                return 0;
 770        }
 771
 772        /*
 773         *      Read router proc directory entry.
 774         *      This is universal routine for reading all entries in /proc/net/wanrouter
 775         *      directory.  Each directory entry contains a pointer to the 'method' for
 776         *      preparing data for that entry.
 777         *      o verify arguments
 778         *      o allocate kernel buffer
 779         *      o call get_info() to prepare data
 780         *      o copy data to user space
 781         *      o release kernel buffer
 782         *
 783         *      Return: number of bytes copied to user space (0, if no data)
 784         *              <0      error
 785         */
 786#ifdef LINUX_2_1
 787        static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
 788                                        loff_t *ppos)
 789        {
 790                struct inode *inode = file->f_dentry->d_inode;
 791                struct proc_dir_entry* dent;
 792                char* page;
 793                int pos, offs, len;
 794
 795                if (count <= 0)
 796                        return 0;
 797                        
 798                dent = inode->u.generic_ip;
 799                if ((dent == NULL) || (dent->get_info == NULL))
 800                        return 0;
 801                        
 802                page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
 803                if (page == NULL)
 804                        return -ENOBUFS;
 805                        
 806                pos = dent->get_info(page, dent->data, 0, 0, 0);
 807                offs = file->f_pos;
 808                if (offs < pos) {
 809                        len = min_t(unsigned int, pos - offs, count);
 810                        if (copy_to_user(buf, (page + offs), len)) {
 811                                kfree(page);
 812                                return -EFAULT;
 813                        }
 814                        file->f_pos += len;
 815                }
 816                else
 817                        len = 0;
 818                kfree(page);
 819                return len;
 820        }
 821
 822#else
 823        static int router_proc_read(
 824                struct inode* inode, struct file* file, char* buf, int count)
 825        {
 826                struct proc_dir_entry* dent;
 827                char* page;
 828                int err, pos, offs, len;
 829
 830                if (count <= 0)
 831                        return 0;
 832                dent = inode->u.generic_ip;
 833                if ((dent == NULL) || (dent->get_info == NULL))
 834                        return -ENODATA;
 835                err = verify_area(VERIFY_WRITE, buf, count);
 836                if (err) return err;
 837
 838                page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
 839                if (page == NULL)
 840                        return -ENOMEM;
 841
 842                pos = dent->get_info(page, dent->data, 0, 0, 0);
 843                offs = file->f_pos;
 844                if (offs < pos) {
 845                        len = min_t(unsigned int, pos - offs, count);
 846                        memcpy_tofs((void*)buf, (void*)(page + offs), len);
 847                        file->f_pos += len;
 848                }
 849                else len = 0;
 850                kfree(page);
 851                return len;
 852        }
 853#endif
 854
 855
 856        /*
 857         *      Prepare data for reading 'Config' entry.
 858         *      Return length of data.
 859         */
 860
 861        static int config_get_info(char* buf, char** start, off_t offs, int len, 
 862                int dummy)
 863        {
 864                int cnt = sizeof(conf_hdr) - 1;
 865                wan_device_t* wandev;
 866                strcpy(buf, conf_hdr);
 867                for (wandev = router_devlist;
 868                     wandev && (cnt < (PROC_BUFSZ - 120));
 869                     wandev = wandev->next) {
 870                        if (wandev->state) cnt += sprintf(&buf[cnt],
 871                                "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
 872                                wandev->name,
 873                                wandev->ioport,
 874                                wandev->irq,
 875                                wandev->dma,
 876                                wandev->maddr,
 877                                wandev->msize,
 878                                wandev->hw_opt[0],
 879                                wandev->hw_opt[1],
 880                                wandev->hw_opt[2],
 881                                wandev->hw_opt[3]);
 882                }
 883
 884                return cnt;
 885        }
 886
 887        /*
 888         *      Prepare data for reading 'Status' entry.
 889         *      Return length of data.
 890         */
 891
 892        static int status_get_info(char* buf, char** start, off_t offs, int len, 
 893                                int dummy)
 894        {
 895                int cnt = 0;
 896                wan_device_t* wandev;
 897
 898                //cnt += sprintf(&buf[cnt], "\nSTATUS:\n\n");
 899                strcpy(&buf[cnt], stat_hdr);
 900                cnt += sizeof(stat_hdr) - 1;
 901
 902                for (wandev = router_devlist;
 903                     wandev && (cnt < (PROC_BUFSZ - 80));
 904                     wandev = wandev->next) {
 905                        if (!wandev->state) continue;
 906                        cnt += sprintf(&buf[cnt],
 907                                "%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
 908                                wandev->name,
 909                                PROT_DECODE(wandev->config_id),
 910                                wandev->config_id == WANCONFIG_FR ? 
 911                                        (wandev->station ? " Node" : " CPE") :
 912                                        (wandev->config_id == WANCONFIG_X25 ?
 913                                        (wandev->station ? " DCE" : " DTE") :
 914                                        (" N/A")),
 915                                wandev->interface ? " V.35" : " RS-232",
 916                                wandev->clocking ? "internal" : "external",
 917                                wandev->bps,
 918                                wandev->mtu,
 919                                wandev->ndev);
 920
 921                        switch (wandev->state) {
 922
 923                        case WAN_UNCONFIGURED:
 924                                cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
 925                                break;
 926
 927                        case WAN_DISCONNECTED:
 928                                cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
 929                                break;
 930
 931                        case WAN_CONNECTING:
 932                                cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
 933                                break;
 934
 935                        case WAN_CONNECTED:
 936                                cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
 937                                break;
 938
 939                        case WAN_FT1_READY:
 940                                cnt += sprintf(&buf[cnt], "%-12s\n", "ft1 ready");
 941                                break;
 942
 943                        default:
 944                                cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
 945                                break;
 946                        }
 947                }
 948                return cnt;
 949        }
 950
 951        /*
 952         *      Prepare data for reading <device> entry.
 953         *      Return length of data.
 954         *
 955         *      On entry, the 'start' argument will contain a pointer to WAN device
 956         *      data space.
 957         */
 958
 959        static int wandev_get_info(char* buf, char** start, off_t offs, int len, 
 960                                int dummy)
 961        {
 962                wan_device_t* wandev = (void*)start;
 963                int cnt = 0;
 964                int rslt = 0;
 965
 966                if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
 967                        return 0;
 968                if (!wandev->state)
 969                        return sprintf(&buf[cnt], "Device is not configured!\n");
 970
 971                /* Update device statistics */
 972                if (wandev->update) {
 973
 974                        rslt = wandev->update(wandev);
 975                        if(rslt) {
 976                                switch (rslt) {
 977                                case -EAGAIN:
 978                                        return sprintf(&buf[cnt], "Device is busy!\n");
 979
 980                                default:
 981                                        return sprintf(&buf[cnt],
 982                                                "Device is not configured!\n");
 983                                }
 984                        }
 985                }
 986
 987                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 988                        "total packets received", wandev->stats.rx_packets);
 989                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 990                        "total packets transmitted", wandev->stats.tx_packets);
 991#ifdef LINUX_2_1
 992                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 993                        "total bytes received", wandev->stats.rx_bytes);
 994                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 995                        "total bytes transmitted", wandev->stats.tx_bytes);
 996#endif
 997                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
 998                        "bad packets received", wandev->stats.rx_errors);
 999                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1000                        "packet transmit problems", wandev->stats.tx_errors);
1001                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1002                        "received frames dropped", wandev->stats.rx_dropped);
1003                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1004                        "transmit frames dropped", wandev->stats.tx_dropped);
1005                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1006                        "multicast packets received", wandev->stats.multicast);
1007                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1008                        "transmit collisions", wandev->stats.collisions);
1009                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1010                        "receive length errors", wandev->stats.rx_length_errors);
1011                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1012                        "receiver overrun errors", wandev->stats.rx_over_errors);
1013                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1014                        "CRC errors", wandev->stats.rx_crc_errors);
1015                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1016                        "frame format errors (aborts)", wandev->stats.rx_frame_errors);
1017                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1018                        "receiver fifo overrun", wandev->stats.rx_fifo_errors);
1019                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1020                        "receiver missed packet", wandev->stats.rx_missed_errors);
1021                cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
1022                        "aborted frames transmitted", wandev->stats.tx_aborted_errors);
1023
1024                return cnt;
1025        }
1026
1027#endif /* End of ifdef LINUX_2_4 */
1028
1029
1030#else
1031
1032/*
1033 *      No /proc - output stubs
1034 */
1035
1036int __init wanrouter_proc_init(void)
1037{
1038        return 0;
1039}
1040
1041void wanrouter_proc_cleanup(void)
1042{
1043        return;
1044}
1045
1046int wanrouter_proc_add(wan_device_t *wandev)
1047{
1048        return 0;
1049}
1050
1051int wanrouter_proc_delete(wan_device_t *wandev)
1052{
1053        return 0;
1054}
1055
1056#endif
1057
1058/*============================================================================
1059 * Write WAN device ???.
1060 * o Find WAN device associated with this node
1061 */
1062#ifdef LINUX_2_0
1063static int device_write(
1064        struct inode* inode, struct file* file, const char* buf, int count)
1065{
1066        int err = verify_area(VERIFY_READ, buf, count);
1067        struct proc_dir_entry* dent;
1068        wan_device_t* wandev;
1069
1070        if (err) return err;
1071
1072        dent = inode->u.generic_ip;
1073        if ((dent == NULL) || (dent->data == NULL))
1074                return -ENODATA;
1075
1076        wandev = dent->data;
1077
1078        printk(KERN_ERR "%s: writing %d bytes to %s...\n",
1079                name_root, count, dent->name);
1080        
1081        return 0;
1082}
1083#endif
1084
1085/*
1086 *      End
1087 */
1088 
1089
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.