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