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 **************************************************/
38 #define min(a,b) (((a)<(b))?(a):(b))
41 #define max(a,b) (((a)>(b))?(a):(b))
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 */
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
);
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
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
=
98 router_proc_read
, /* read */
104 NULL
, /* no special open code */
106 NULL
, /* no special release code */
107 NULL
/* can't fsync */
110 static struct inode_operations router_inode
=
122 NULL
, /* follow link */
125 NULL
, /* writepage */
132 * /proc/net/router/<device> file and inode operations
135 static struct file_operations wandev_fops
=
138 router_proc_read
, /* read */
142 wanrouter_ioctl
, /* ioctl */
144 NULL
, /* no special open code */
146 NULL
, /* no special release code */
147 NULL
/* can't fsync */
150 static struct inode_operations wandev_inode
=
163 NULL
, /* follow_link */
165 NULL
, /* writepage */
172 * Proc filesystem derectory entries.
179 static struct proc_dir_entry proc_router
=
182 sizeof(name_root
) - 1, /* .namelen */
183 name_root
, /* .name */
184 0555 | S_IFDIR
, /* .mode */
189 &proc_dir_inode_operations
, /* .ops */
190 NULL
, /* .get_info */
191 NULL
, /* .fill_node */
199 * /proc/net/router/config
202 static struct proc_dir_entry proc_router_conf
=
205 sizeof(name_conf
) - 1, /* .namelen */
206 name_conf
, /* .name */
207 0444 | S_IFREG
, /* .mode */
212 &router_inode
, /* .ops */
213 &config_get_info
, /* .get_info */
214 NULL
, /* .fill_node */
222 * /proc/net/router/status
225 static struct proc_dir_entry proc_router_stat
=
228 sizeof(name_stat
) - 1, /* .namelen */
229 name_stat
, /* .name */
230 0444 | S_IFREG
, /* .mode */
235 &router_inode
, /* .ops */
236 status_get_info
, /* .get_info */
237 NULL
, /* .fill_node */
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"
255 * Interface functions
259 * Initialize router proc interface.
262 __initfunc(int wanrouter_proc_init (void))
264 int err
= proc_register(proc_net
, &proc_router
);
268 proc_register(&proc_router
, &proc_router_conf
);
269 proc_register(&proc_router
, &proc_router_stat
);
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
)
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
)
313 proc_unregister(&proc_router
, wandev
->dent
.low_ino
);
317 /****** Proc filesystem entry points ****************************************/
320 * Verify access rights.
323 static int router_proc_perms (struct inode
* inode
, int op
)
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.
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)
343 static ssize_t
router_proc_read(struct file
* file
, char* buf
, size_t count
,
346 struct inode
*inode
= file
->f_dentry
->d_inode
;
347 struct proc_dir_entry
* dent
;
354 dent
= inode
->u
.generic_ip
;
355 if ((dent
== NULL
) || (dent
->get_info
== NULL
))
358 page
= kmalloc(PROC_BUFSZ
, GFP_KERNEL
);
362 pos
= dent
->get_info(page
, dent
->data
, 0, 0, 0);
366 len
= min(pos
- offs
, count
);
367 if(copy_to_user(buf
, (page
+ offs
), 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
,
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",
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
,
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 |",
428 wandev
->station
? " DCE" : " DTE",
429 wandev
->interface
? " V.35" : " RS-232",
430 wandev
->clocking
? "internal" : "external",
435 switch (wandev
->state
)
437 case WAN_UNCONFIGURED
:
438 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "unconfigured");
441 case WAN_DISCONNECTED
:
442 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "disconnected");
446 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "connecting");
450 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "connected");
454 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "invalid");
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
469 static int wandev_get_info(char* buf
, char** start
, off_t offs
, int len
,
472 wan_device_t
* wandev
= (void*)start
;
475 if ((wandev
== NULL
) || (wandev
->magic
!= ROUTER_MAGIC
))
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
)