Import 2.3.9pre7
[davej-history.git] / net / wanrouter / wanproc.c
blobd8bd1e33d9af75537e5b3c0c3f8fb09da9b81e77
1 /*****************************************************************************
2 * wanproc.c WAN Router Module. /proc filesystem interface.
4 * This module is completely hardware-independent and provides
5 * access to the router using Linux /proc filesystem.
7 * Author: Gene Kozin <genek@compuserve.com>
9 * Copyright: (c) 1995-1997 Sangoma Technologies Inc.
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 29, 1997 Alan Cox Merged with 1.0.3 vendor code
17 * Jan 29, 1997 Gene Kozin v1.0.1. Implemented /proc read routines
18 * Jan 30, 1997 Alan Cox Hacked around for 2.1
19 * Dec 13, 1996 Gene Kozin Initial version (based on Sangoma's WANPIPE)
20 *****************************************************************************/
22 #include <linux/config.h>
23 #include <linux/stddef.h> /* offsetof(), etc. */
24 #include <linux/errno.h> /* return codes */
25 #include <linux/kernel.h>
26 #include <linux/malloc.h> /* kmalloc(), kfree() */
27 #include <linux/mm.h> /* verify_area(), etc. */
28 #include <linux/string.h> /* inline mem*, str* functions */
29 #include <linux/init.h> /* __initfunc et al. */
30 #include <asm/segment.h> /* kernel <-> user copy */
31 #include <asm/byteorder.h> /* htons(), etc. */
32 #include <asm/uaccess.h> /* copy_to_user */
33 #include <asm/io.h>
34 #include <linux/wanrouter.h> /* WAN router API definitions */
37 /****** Defines and Macros **************************************************/
39 #ifndef min
40 #define min(a,b) (((a)<(b))?(a):(b))
41 #endif
42 #ifndef max
43 #define max(a,b) (((a)>(b))?(a):(b))
44 #endif
46 #define PROC_BUFSZ 4000 /* buffer size for printing proc info */
48 /****** Data Types **********************************************************/
50 typedef struct wan_stat_entry
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;
58 /****** Function Prototypes *************************************************/
60 #ifdef CONFIG_PROC_FS
62 /* Proc filesystem interface */
63 static int router_proc_perms(struct inode *, int);
64 static ssize_t router_proc_read(struct file* file, char* buf, size_t count, loff_t *ppos);
66 /* Methods for preparing data for reading proc entries */
68 static int config_get_info(char* buf, char** start, off_t offs, int len, int dummy);
69 static int status_get_info(char* buf, char** start, off_t offs, int len, int dummy);
70 static int wandev_get_info(char* buf, char** start, off_t offs, int len, int dummy);
72 /* Miscellaneous */
75 * Global Data
79 * Names of the proc directory entries
82 static char name_root[] = ROUTER_NAME;
83 static char name_conf[] = "config";
84 static char name_stat[] = "status";
87 * Structures for interfacing with the /proc filesystem.
88 * Router creates its own directory /proc/net/router with the folowing
89 * entries:
90 * config device configuration
91 * status global device statistics
92 * <device> entry for each WAN device
96 * Generic /proc/net/router/<file> file and inode operations
99 static struct file_operations router_fops =
101 NULL, /* lseek */
102 router_proc_read, /* read */
103 NULL, /* write */
104 NULL, /* readdir */
105 NULL, /* select */
106 NULL, /* ioctl */
107 NULL, /* mmap */
108 NULL, /* no special open code */
109 NULL, /* flush */
110 NULL, /* no special release code */
111 NULL /* can't fsync */
114 static struct inode_operations router_inode =
116 &router_fops,
117 NULL, /* create */
118 NULL, /* lookup */
119 NULL, /* link */
120 NULL, /* unlink */
121 NULL, /* symlink */
122 NULL, /* mkdir */
123 NULL, /* rmdir */
124 NULL, /* mknod */
125 NULL, /* rename */
126 NULL, /* follow link */
127 NULL, /* readlink */
128 NULL, /* readpage */
129 NULL, /* writepage */
130 NULL, /* get_block */
131 NULL, /* truncate */
132 router_proc_perms
136 * /proc/net/router/<device> file and inode operations
139 static struct file_operations wandev_fops =
141 NULL, /* lseek */
142 router_proc_read, /* read */
143 NULL, /* write */
144 NULL, /* readdir */
145 NULL, /* select */
146 wanrouter_ioctl, /* ioctl */
147 NULL, /* mmap */
148 NULL, /* no special open code */
149 NULL, /* flush */
150 NULL, /* no special release code */
151 NULL /* can't fsync */
154 static struct inode_operations wandev_inode =
156 &wandev_fops,
157 NULL, /* create */
158 NULL, /* lookup */
159 NULL, /* link */
160 NULL, /* unlink */
161 NULL, /* symlink */
162 NULL, /* mkdir */
163 NULL, /* rmdir */
164 NULL, /* mknod */
165 NULL, /* rename */
166 NULL, /* readlink */
167 NULL, /* follow_link */
168 NULL, /* readpage */
169 NULL, /* writepage */
170 NULL, /* get_block */
171 NULL, /* truncate */
172 router_proc_perms
176 * Proc filesystem derectory entries.
180 * /proc/net/router
183 static struct proc_dir_entry proc_router =
185 0, /* .low_ino */
186 sizeof(name_root) - 1, /* .namelen */
187 name_root, /* .name */
188 0555 | S_IFDIR, /* .mode */
189 2, /* .nlink */
190 0, /* .uid */
191 0, /* .gid */
192 0, /* .size */
193 &proc_dir_inode_operations, /* .ops */
194 NULL, /* .get_info */
195 NULL, /* .fill_node */
196 NULL, /* .next */
197 NULL, /* .parent */
198 NULL, /* .subdir */
199 NULL, /* .data */
203 * /proc/net/router/config
206 static struct proc_dir_entry proc_router_conf =
208 0, /* .low_ino */
209 sizeof(name_conf) - 1, /* .namelen */
210 name_conf, /* .name */
211 0444 | S_IFREG, /* .mode */
212 1, /* .nlink */
213 0, /* .uid */
214 0, /* .gid */
215 0, /* .size */
216 &router_inode, /* .ops */
217 &config_get_info, /* .get_info */
218 NULL, /* .fill_node */
219 NULL, /* .next */
220 NULL, /* .parent */
221 NULL, /* .subdir */
222 NULL, /* .data */
226 * /proc/net/router/status
229 static struct proc_dir_entry proc_router_stat =
231 0, /* .low_ino */
232 sizeof(name_stat) - 1, /* .namelen */
233 name_stat, /* .name */
234 0444 | S_IFREG, /* .mode */
235 1, /* .nlink */
236 0, /* .uid */
237 0, /* .gid */
238 0, /* .size */
239 &router_inode, /* .ops */
240 status_get_info, /* .get_info */
241 NULL, /* .fill_node */
242 NULL, /* .next */
243 NULL, /* .parent */
244 NULL, /* .subdir */
245 NULL, /* .data */
248 /* Strings */
249 static char conf_hdr[] =
250 "Device name | port |IRQ|DMA| mem.addr |mem.size|"
251 "option1|option2|option3|option4\n";
253 static char stat_hdr[] =
254 "Device name |station|interface|clocking|baud rate| MTU |ndev"
255 "|link state\n";
259 * Interface functions
263 * Initialize router proc interface.
266 __initfunc(int wanrouter_proc_init (void))
268 int err = proc_register(proc_net, &proc_router);
270 if (!err)
272 proc_register(&proc_router, &proc_router_conf);
273 proc_register(&proc_router, &proc_router_stat);
275 return err;
279 * Clean up router proc interface.
282 void wanrouter_proc_cleanup (void)
284 proc_unregister(&proc_router, proc_router_conf.low_ino);
285 proc_unregister(&proc_router, proc_router_stat.low_ino);
286 proc_unregister(proc_net, proc_router.low_ino);
290 * Add directory entry for WAN device.
293 int wanrouter_proc_add (wan_device_t* wandev)
295 if (wandev->magic != ROUTER_MAGIC)
296 return -EINVAL;
298 memset(&wandev->dent, 0, sizeof(wandev->dent));
299 wandev->dent.namelen = strlen(wandev->name);
300 wandev->dent.name = wandev->name;
301 wandev->dent.mode = 0444 | S_IFREG;
302 wandev->dent.nlink = 1;
303 wandev->dent.ops = &wandev_inode;
304 wandev->dent.get_info = &wandev_get_info;
305 wandev->dent.data = wandev;
306 return proc_register(&proc_router, &wandev->dent);
310 * Delete directory entry for WAN device.
313 int wanrouter_proc_delete(wan_device_t* wandev)
315 if (wandev->magic != ROUTER_MAGIC)
316 return -EINVAL;
317 proc_unregister(&proc_router, wandev->dent.low_ino);
318 return 0;
321 /****** Proc filesystem entry points ****************************************/
324 * Verify access rights.
327 static int router_proc_perms (struct inode* inode, int op)
329 return 0;
333 * Read router proc directory entry.
334 * This is universal routine for reading all entries in /proc/net/router
335 * directory. Each directory entry contains a pointer to the 'method' for
336 * preparing data for that entry.
337 * o verify arguments
338 * o allocate kernel buffer
339 * o call get_info() to prepare data
340 * o copy data to user space
341 * o release kernel buffer
343 * Return: number of bytes copied to user space (0, if no data)
344 * <0 error
347 static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
348 loff_t *ppos)
350 struct inode *inode = file->f_dentry->d_inode;
351 struct proc_dir_entry* dent;
352 char* page;
353 int pos, offs, len;
355 if (count <= 0)
356 return 0;
358 dent = inode->u.generic_ip;
359 if ((dent == NULL) || (dent->get_info == NULL))
360 return 0;
362 page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
363 if (page == NULL)
364 return -ENOBUFS;
366 pos = dent->get_info(page, dent->data, 0, 0, 0);
367 offs = file->f_pos;
368 if (offs < pos)
370 len = min(pos - offs, count);
371 if(copy_to_user(buf, (page + offs), len))
372 return -EFAULT;
373 file->f_pos += len;
375 else
376 len = 0;
377 kfree(page);
378 return len;
382 * Prepare data for reading 'Config' entry.
383 * Return length of data.
386 static int config_get_info(char* buf, char** start, off_t offs, int len,
387 int dummy)
389 int cnt = sizeof(conf_hdr) - 1;
390 wan_device_t* wandev;
391 strcpy(buf, conf_hdr);
392 for (wandev = router_devlist;
393 wandev && (cnt < (PROC_BUFSZ - 120));
394 wandev = wandev->next)
396 if (wandev->state) cnt += sprintf(&buf[cnt],
397 "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
398 wandev->name,
399 wandev->ioport,
400 wandev->irq,
401 wandev->dma,
402 virt_to_phys(wandev->maddr),
403 wandev->msize,
404 wandev->hw_opt[0],
405 wandev->hw_opt[1],
406 wandev->hw_opt[2],
407 wandev->hw_opt[3]);
410 return cnt;
414 * Prepare data for reading 'Status' entry.
415 * Return length of data.
418 static int status_get_info(char* buf, char** start, off_t offs, int len,
419 int dummy)
421 int cnt = sizeof(stat_hdr) - 1;
422 wan_device_t* wandev;
423 strcpy(buf, stat_hdr);
424 for (wandev = router_devlist;
425 wandev && (cnt < (PROC_BUFSZ - 80));
426 wandev = wandev->next)
428 if (!wandev->state) continue;
429 cnt += sprintf(&buf[cnt],
430 "%-15s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
431 wandev->name,
432 wandev->station ? " DCE" : " DTE",
433 wandev->interface ? " V.35" : " RS-232",
434 wandev->clocking ? "internal" : "external",
435 wandev->bps,
436 wandev->mtu,
437 wandev->ndev)
439 switch (wandev->state)
441 case WAN_UNCONFIGURED:
442 cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
443 break;
445 case WAN_DISCONNECTED:
446 cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
447 break;
449 case WAN_CONNECTING:
450 cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
451 break;
453 case WAN_CONNECTED:
454 cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
455 break;
457 default:
458 cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
459 break;
462 return cnt;
466 * Prepare data for reading <device> entry.
467 * Return length of data.
469 * On entry, the 'start' argument will contain a pointer to WAN device
470 * data space.
473 static int wandev_get_info(char* buf, char** start, off_t offs, int len,
474 int dummy)
476 wan_device_t* wandev = (void*)start;
477 int cnt = 0;
479 if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
480 return 0;
481 if (!wandev->state)
482 return sprintf(&buf[cnt], "device is not configured!\n")
485 /* Update device statistics */
486 if (wandev->update) wandev->update(wandev);
488 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
489 "total frames received", wandev->stats.rx_packets)
491 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
492 "receiver overrun errors", wandev->stats.rx_over_errors)
494 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
495 "CRC errors", wandev->stats.rx_crc_errors)
497 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
498 "frame length errors", wandev->stats.rx_length_errors)
500 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
501 "frame format errors", wandev->stats.rx_frame_errors)
503 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
504 "aborted frames received", wandev->stats.rx_missed_errors)
506 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
507 "reveived frames dropped", wandev->stats.rx_dropped)
509 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
510 "other receive errors", wandev->stats.rx_errors)
512 cnt += sprintf(&buf[cnt], "\n%30s: %12lu\n",
513 "total frames transmitted", wandev->stats.tx_packets)
515 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
516 "aborted frames transmitted", wandev->stats.tx_aborted_errors)
518 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
519 "transmit frames dropped", wandev->stats.tx_dropped)
521 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
522 "transmit collisions", wandev->stats.collisions)
524 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
525 "other transmit errors", wandev->stats.tx_errors)
527 return cnt;
531 * End
534 #else
537 * No /proc - output stubs
540 __initfunc(int wanrouter_proc_init(void))
542 return 0;
545 void wanrouter_proc_cleanup(void)
547 return;
550 int wanrouter_proc_add(wan_device_t *wandev)
552 return 0;
555 int wanrouter_proc_delete(wan_device_t *wandev)
557 return 0;
560 #endif