Import 2.1.118
[davej-history.git] / net / wanrouter / wanproc.c
blobb619e1daebdc633f2647a1c4d369201273fcadee
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/stddef.h> /* offsetof(), etc. */
23 #include <linux/errno.h> /* return codes */
24 #include <linux/kernel.h>
25 #include <linux/malloc.h> /* kmalloc(), kfree() */
26 #include <linux/mm.h> /* verify_area(), etc. */
27 #include <linux/string.h> /* inline mem*, str* functions */
28 #include <linux/init.h> /* __initfunc et al. */
29 #include <asm/segment.h> /* kernel <-> user copy */
30 #include <asm/byteorder.h> /* htons(), etc. */
31 #include <asm/uaccess.h> /* copy_to_user */
32 #include <linux/wanrouter.h> /* WAN router API definitions */
35 /****** Defines and Macros **************************************************/
37 #ifndef min
38 #define min(a,b) (((a)<(b))?(a):(b))
39 #endif
40 #ifndef max
41 #define max(a,b) (((a)>(b))?(a):(b))
42 #endif
44 #define PROC_BUFSZ 4000 /* buffer size for printing proc info */
46 /****** Data Types **********************************************************/
48 typedef struct wan_stat_entry
50 struct wan_stat_entry * next;
51 char *description; /* description string */
52 void *data; /* -> data */
53 unsigned data_type; /* data type */
54 } wan_stat_entry_t;
56 /****** Function Prototypes *************************************************/
58 /* Proc filesystem interface */
59 static int router_proc_perms(struct inode *, int);
60 static ssize_t router_proc_read(struct file* file, char* buf, size_t count, loff_t *ppos);
62 /* Methods for preparing data for reading proc entries */
64 static int config_get_info(char* buf, char** start, off_t offs, int len, int dummy);
65 static int status_get_info(char* buf, char** start, off_t offs, int len, int dummy);
66 static int wandev_get_info(char* buf, char** start, off_t offs, int len, int dummy);
68 /* Miscellaneous */
71 * Global Data
75 * Names of the proc directory entries
78 static char name_root[] = ROUTER_NAME;
79 static char name_conf[] = "config";
80 static char name_stat[] = "status";
83 * Structures for interfacing with the /proc filesystem.
84 * Router creates its own directory /proc/net/router with the folowing
85 * entries:
86 * config device configuration
87 * status global device statistics
88 * <device> entry for each WAN device
92 * Generic /proc/net/router/<file> file and inode operations
95 static struct file_operations router_fops =
97 NULL, /* lseek */
98 router_proc_read, /* read */
99 NULL, /* write */
100 NULL, /* readdir */
101 NULL, /* select */
102 NULL, /* ioctl */
103 NULL, /* mmap */
104 NULL, /* no special open code */
105 NULL, /* flush */
106 NULL, /* no special release code */
107 NULL /* can't fsync */
110 static struct inode_operations router_inode =
112 &router_fops,
113 NULL, /* create */
114 NULL, /* lookup */
115 NULL, /* link */
116 NULL, /* unlink */
117 NULL, /* symlink */
118 NULL, /* mkdir */
119 NULL, /* rmdir */
120 NULL, /* mknod */
121 NULL, /* rename */
122 NULL, /* follow link */
123 NULL, /* readlink */
124 NULL, /* readpage */
125 NULL, /* writepage */
126 NULL, /* bmap */
127 NULL, /* truncate */
128 router_proc_perms
132 * /proc/net/router/<device> file and inode operations
135 static struct file_operations wandev_fops =
137 NULL, /* lseek */
138 router_proc_read, /* read */
139 NULL, /* write */
140 NULL, /* readdir */
141 NULL, /* select */
142 wanrouter_ioctl, /* ioctl */
143 NULL, /* mmap */
144 NULL, /* no special open code */
145 NULL, /* flush */
146 NULL, /* no special release code */
147 NULL /* can't fsync */
150 static struct inode_operations wandev_inode =
152 &wandev_fops,
153 NULL, /* create */
154 NULL, /* lookup */
155 NULL, /* link */
156 NULL, /* unlink */
157 NULL, /* symlink */
158 NULL, /* mkdir */
159 NULL, /* rmdir */
160 NULL, /* mknod */
161 NULL, /* rename */
162 NULL, /* readlink */
163 NULL, /* follow_link */
164 NULL, /* readpage */
165 NULL, /* writepage */
166 NULL, /* bmap */
167 NULL, /* truncate */
168 router_proc_perms
172 * Proc filesystem derectory entries.
176 * /proc/net/router
179 static struct proc_dir_entry proc_router =
181 0, /* .low_ino */
182 sizeof(name_root) - 1, /* .namelen */
183 name_root, /* .name */
184 0555 | S_IFDIR, /* .mode */
185 2, /* .nlink */
186 0, /* .uid */
187 0, /* .gid */
188 0, /* .size */
189 &proc_dir_inode_operations, /* .ops */
190 NULL, /* .get_info */
191 NULL, /* .fill_node */
192 NULL, /* .next */
193 NULL, /* .parent */
194 NULL, /* .subdir */
195 NULL, /* .data */
199 * /proc/net/router/config
202 static struct proc_dir_entry proc_router_conf =
204 0, /* .low_ino */
205 sizeof(name_conf) - 1, /* .namelen */
206 name_conf, /* .name */
207 0444 | S_IFREG, /* .mode */
208 1, /* .nlink */
209 0, /* .uid */
210 0, /* .gid */
211 0, /* .size */
212 &router_inode, /* .ops */
213 &config_get_info, /* .get_info */
214 NULL, /* .fill_node */
215 NULL, /* .next */
216 NULL, /* .parent */
217 NULL, /* .subdir */
218 NULL, /* .data */
222 * /proc/net/router/status
225 static struct proc_dir_entry proc_router_stat =
227 0, /* .low_ino */
228 sizeof(name_stat) - 1, /* .namelen */
229 name_stat, /* .name */
230 0444 | S_IFREG, /* .mode */
231 1, /* .nlink */
232 0, /* .uid */
233 0, /* .gid */
234 0, /* .size */
235 &router_inode, /* .ops */
236 status_get_info, /* .get_info */
237 NULL, /* .fill_node */
238 NULL, /* .next */
239 NULL, /* .parent */
240 NULL, /* .subdir */
241 NULL, /* .data */
244 /* Strings */
245 static char conf_hdr[] =
246 "Device name | port |IRQ|DMA|mem.addr|mem.size|"
247 "option1|option2|option3|option4\n";
249 static char stat_hdr[] =
250 "Device name |station|interface|clocking|baud rate| MTU |ndev"
251 "|link state\n";
255 * Interface functions
259 * Initialize router proc interface.
262 __initfunc(int wanrouter_proc_init (void))
264 int err = proc_register(proc_net, &proc_router);
266 if (!err)
268 proc_register(&proc_router, &proc_router_conf);
269 proc_register(&proc_router, &proc_router_stat);
271 return err;
275 * Clean up router proc interface.
278 void wanrouter_proc_cleanup (void)
280 proc_unregister(&proc_router, proc_router_conf.low_ino);
281 proc_unregister(&proc_router, proc_router_stat.low_ino);
282 proc_unregister(proc_net, proc_router.low_ino);
286 * Add directory entry for WAN device.
289 int wanrouter_proc_add (wan_device_t* wandev)
291 if (wandev->magic != ROUTER_MAGIC)
292 return -EINVAL;
294 memset(&wandev->dent, 0, sizeof(wandev->dent));
295 wandev->dent.namelen = strlen(wandev->name);
296 wandev->dent.name = wandev->name;
297 wandev->dent.mode = 0444 | S_IFREG;
298 wandev->dent.nlink = 1;
299 wandev->dent.ops = &wandev_inode;
300 wandev->dent.get_info = &wandev_get_info;
301 wandev->dent.data = wandev;
302 return proc_register(&proc_router, &wandev->dent);
306 * Delete directory entry for WAN device.
309 int wanrouter_proc_delete(wan_device_t* wandev)
311 if (wandev->magic != ROUTER_MAGIC)
312 return -EINVAL;
313 proc_unregister(&proc_router, wandev->dent.low_ino);
314 return 0;
317 /****** Proc filesystem entry points ****************************************/
320 * Verify access rights.
323 static int router_proc_perms (struct inode* inode, int op)
325 return 0;
329 * Read router proc directory entry.
330 * This is universal routine for reading all entries in /proc/net/router
331 * directory. Each directory entry contains a pointer to the 'method' for
332 * preparing data for that entry.
333 * o verify arguments
334 * o allocate kernel buffer
335 * o call get_info() to prepare data
336 * o copy data to user space
337 * o release kernel buffer
339 * Return: number of bytes copied to user space (0, if no data)
340 * <0 error
343 static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
344 loff_t *ppos)
346 struct inode *inode = file->f_dentry->d_inode;
347 struct proc_dir_entry* dent;
348 char* page;
349 int pos, offs, len;
351 if (count <= 0)
352 return 0;
354 dent = inode->u.generic_ip;
355 if ((dent == NULL) || (dent->get_info == NULL))
356 return 0;
358 page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
359 if (page == NULL)
360 return -ENOBUFS;
362 pos = dent->get_info(page, dent->data, 0, 0, 0);
363 offs = file->f_pos;
364 if (offs < pos)
366 len = min(pos - offs, count);
367 if(copy_to_user(buf, (page + offs), len))
368 return -EFAULT;
369 file->f_pos += len;
371 else
372 len = 0;
373 kfree(page);
374 return len;
378 * Prepare data for reading 'Config' entry.
379 * Return length of data.
382 static int config_get_info(char* buf, char** start, off_t offs, int len,
383 int dummy)
385 int cnt = sizeof(conf_hdr) - 1;
386 wan_device_t* wandev;
387 strcpy(buf, conf_hdr);
388 for (wandev = router_devlist;
389 wandev && (cnt < (PROC_BUFSZ - 80));
390 wandev = wandev->next)
392 if (wandev->state) cnt += sprintf(&buf[cnt],
393 "%-15s|0x%-4X|%3u|%3u|0x%-6lX|0x%-6X|%7u|%7u|%7u|%7u\n",
394 wandev->name,
395 wandev->ioport,
396 wandev->irq,
397 wandev->dma,
398 wandev->maddr,
399 wandev->msize,
400 wandev->hw_opt[0],
401 wandev->hw_opt[1],
402 wandev->hw_opt[2],
403 wandev->hw_opt[3]);
406 return cnt;
410 * Prepare data for reading 'Status' entry.
411 * Return length of data.
414 static int status_get_info(char* buf, char** start, off_t offs, int len,
415 int dummy)
417 int cnt = sizeof(stat_hdr) - 1;
418 wan_device_t* wandev;
419 strcpy(buf, stat_hdr);
420 for (wandev = router_devlist;
421 wandev && (cnt < (PROC_BUFSZ - 80));
422 wandev = wandev->next)
424 if (!wandev->state) continue;
425 cnt += sprintf(&buf[cnt],
426 "%-15s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
427 wandev->name,
428 wandev->station ? " DCE" : " DTE",
429 wandev->interface ? " V.35" : " RS-232",
430 wandev->clocking ? "internal" : "external",
431 wandev->bps,
432 wandev->mtu,
433 wandev->ndev)
435 switch (wandev->state)
437 case WAN_UNCONFIGURED:
438 cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
439 break;
441 case WAN_DISCONNECTED:
442 cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
443 break;
445 case WAN_CONNECTING:
446 cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
447 break;
449 case WAN_CONNECTED:
450 cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
451 break;
453 default:
454 cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
455 break;
458 return cnt;
462 * Prepare data for reading <device> entry.
463 * Return length of data.
465 * On entry, the 'start' argument will contain a pointer to WAN device
466 * data space.
469 static int wandev_get_info(char* buf, char** start, off_t offs, int len,
470 int dummy)
472 wan_device_t* wandev = (void*)start;
473 int cnt = 0;
475 if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
476 return 0;
477 if (!wandev->state)
478 return sprintf(&buf[cnt], "device is not configured!\n")
481 /* Update device statistics */
482 if (wandev->update) wandev->update(wandev);
484 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
485 "total frames received", wandev->stats.rx_packets)
487 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
488 "receiver overrun errors", wandev->stats.rx_over_errors)
490 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
491 "CRC errors", wandev->stats.rx_crc_errors)
493 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
494 "frame length errors", wandev->stats.rx_length_errors)
496 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
497 "frame format errors", wandev->stats.rx_frame_errors)
499 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
500 "aborted frames received", wandev->stats.rx_missed_errors)
502 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
503 "reveived frames dropped", wandev->stats.rx_dropped)
505 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
506 "other receive errors", wandev->stats.rx_errors)
508 cnt += sprintf(&buf[cnt], "\n%30s: %12lu\n",
509 "total frames transmitted", wandev->stats.tx_packets)
511 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
512 "aborted frames transmitted", wandev->stats.tx_aborted_errors)
514 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
515 "transmit frames dropped", wandev->stats.tx_dropped)
517 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
518 "transmit collisions", wandev->stats.collisions)
520 cnt += sprintf(&buf[cnt], "%30s: %12lu\n",
521 "other transmit errors", wandev->stats.tx_errors)
523 return cnt;
527 * End