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 */
34 #include <linux/wanrouter.h> /* WAN router API definitions */
37 /****** Defines and Macros **************************************************/
40 #define min(a,b) (((a)<(b))?(a):(b))
43 #define max(a,b) (((a)>(b))?(a):(b))
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 */
58 /****** Function Prototypes *************************************************/
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
);
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
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
=
102 router_proc_read
, /* read */
108 NULL
, /* no special open code */
110 NULL
, /* no special release code */
111 NULL
/* can't fsync */
114 static struct inode_operations router_inode
=
126 NULL
, /* follow link */
129 NULL
, /* writepage */
130 NULL
, /* get_block */
136 * /proc/net/router/<device> file and inode operations
139 static struct file_operations wandev_fops
=
142 router_proc_read
, /* read */
146 wanrouter_ioctl
, /* ioctl */
148 NULL
, /* no special open code */
150 NULL
, /* no special release code */
151 NULL
/* can't fsync */
154 static struct inode_operations wandev_inode
=
167 NULL
, /* follow_link */
169 NULL
, /* writepage */
170 NULL
, /* get_block */
176 * Proc filesystem derectory entries.
183 static struct proc_dir_entry proc_router
=
186 sizeof(name_root
) - 1, /* .namelen */
187 name_root
, /* .name */
188 0555 | S_IFDIR
, /* .mode */
193 &proc_dir_inode_operations
, /* .ops */
194 NULL
, /* .get_info */
195 NULL
, /* .fill_node */
203 * /proc/net/router/config
206 static struct proc_dir_entry proc_router_conf
=
209 sizeof(name_conf
) - 1, /* .namelen */
210 name_conf
, /* .name */
211 0444 | S_IFREG
, /* .mode */
216 &router_inode
, /* .ops */
217 &config_get_info
, /* .get_info */
218 NULL
, /* .fill_node */
226 * /proc/net/router/status
229 static struct proc_dir_entry proc_router_stat
=
232 sizeof(name_stat
) - 1, /* .namelen */
233 name_stat
, /* .name */
234 0444 | S_IFREG
, /* .mode */
239 &router_inode
, /* .ops */
240 status_get_info
, /* .get_info */
241 NULL
, /* .fill_node */
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"
259 * Interface functions
263 * Initialize router proc interface.
266 __initfunc(int wanrouter_proc_init (void))
268 int err
= proc_register(proc_net
, &proc_router
);
272 proc_register(&proc_router
, &proc_router_conf
);
273 proc_register(&proc_router
, &proc_router_stat
);
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
)
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
)
317 proc_unregister(&proc_router
, wandev
->dent
.low_ino
);
321 /****** Proc filesystem entry points ****************************************/
324 * Verify access rights.
327 static int router_proc_perms (struct inode
* inode
, int op
)
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.
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)
347 static ssize_t
router_proc_read(struct file
* file
, char* buf
, size_t count
,
350 struct inode
*inode
= file
->f_dentry
->d_inode
;
351 struct proc_dir_entry
* dent
;
358 dent
= inode
->u
.generic_ip
;
359 if ((dent
== NULL
) || (dent
->get_info
== NULL
))
362 page
= kmalloc(PROC_BUFSZ
, GFP_KERNEL
);
366 pos
= dent
->get_info(page
, dent
->data
, 0, 0, 0);
370 len
= min(pos
- offs
, count
);
371 if(copy_to_user(buf
, (page
+ offs
), 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
,
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",
402 virt_to_phys(wandev
->maddr
),
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
,
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 |",
432 wandev
->station
? " DCE" : " DTE",
433 wandev
->interface
? " V.35" : " RS-232",
434 wandev
->clocking
? "internal" : "external",
439 switch (wandev
->state
)
441 case WAN_UNCONFIGURED
:
442 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "unconfigured");
445 case WAN_DISCONNECTED
:
446 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "disconnected");
450 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "connecting");
454 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "connected");
458 cnt
+= sprintf(&buf
[cnt
], "%-12s\n", "invalid");
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
473 static int wandev_get_info(char* buf
, char** start
, off_t offs
, int len
,
476 wan_device_t
* wandev
= (void*)start
;
479 if ((wandev
== NULL
) || (wandev
->magic
!= ROUTER_MAGIC
))
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
)
537 * No /proc - output stubs
540 __initfunc(int wanrouter_proc_init(void))
545 void wanrouter_proc_cleanup(void)
550 int wanrouter_proc_add(wan_device_t
*wandev
)
555 int wanrouter_proc_delete(wan_device_t
*wandev
)