wanproc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:27k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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