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
23 #include <linux/version.h>
24 #include <linux/config.h>
25 #include <linux/stddef.h> /* offsetof(), etc. */
26 #include <linux/errno.h> /* return codes */
27 #include <linux/kernel.h>
28 #include <linux/malloc.h> /* kmalloc(), kfree() */
29 #include <linux/mm.h> /* verify_area(), etc. */
30 #include <linux/string.h> /* inline mem*, str* functions */
31 #include <linux/init.h> /* __init et al. */
32 #include <asm/segment.h> /* kernel <-> user copy */
33 #include <asm/byteorder.h> /* htons(), etc. */
34 #include <asm/uaccess.h> /* copy_to_user */
35 #include <asm/io.h>
36 #include <linux/wanrouter.h> /* WAN router API definitions */
37
38
39 /****** Defines and Macros **************************************************/
40
41 #define PROC_STATS_FORMAT "%30s: %12lu\n"
42
43 #ifndef min
44 #define min(a,b) (((a)<(b))?(a):(b))
45 #endif
46 #ifndef max
47 #define max(a,b) (((a)>(b))?(a):(b))
48 #endif
49
50 #define PROC_BUFSZ 4000 /* buffer size for printing proc info */
51
52
53 /****** Data Types **********************************************************/
54
55 typedef struct wan_stat_entry
56 {
57 struct wan_stat_entry *next;
58 char *description; /* description string */
59 void *data; /* -> data */
60 unsigned data_type; /* data type */
61 } wan_stat_entry_t;
62
63 /****** Function Prototypes *************************************************/
64
65 #ifdef CONFIG_PROC_FS
66
67 /* Proc filesystem interface */
68 static int router_proc_perms(struct inode *, int);
69 static ssize_t router_proc_read(struct file* file, char* buf, size_t count, loff_t *ppos);
70
71 /* Methods for preparing data for reading proc entries */
72
73 static int config_get_info(char* buf, char** start, off_t offs, int len);
74 static int status_get_info(char* buf, char** start, off_t offs, int len);
75 static int wandev_get_info(char* buf, char** start, off_t offs, int len);
76
77 /* Miscellaneous */
78
79 /*
80 * Structures for interfacing with the /proc filesystem.
81 * Router creates its own directory /proc/net/router with the folowing
82 * entries:
83 * config device configuration
84 * status global device statistics
85 * <device> entry for each WAN device
86 */
87
88 /*
89 * Generic /proc/net/router/<file> file and inode operations
90 */
91 static struct file_operations router_fops =
92 {
93 read: router_proc_read,
94 };
95
96 static struct inode_operations router_inode =
97 {
98 permission: router_proc_perms,
99 };
100
101 /*
102 * /proc/net/router/<device> file operations
103 */
104
105 static struct file_operations wandev_fops =
106 {
107 read: router_proc_read,
108 ioctl: wanrouter_ioctl,
109 };
110
111 /*
112 * /proc/net/router
113 */
114
115 static struct proc_dir_entry *proc_router;
116
117 /* Strings */
118 static char conf_hdr[] =
119 "Device name | port |IRQ|DMA| mem.addr |mem.size|"
120 "option1|option2|option3|option4\n";
121
122 static char stat_hdr[] =
123 "Device name |station|interface|clocking|baud rate| MTU |ndev"
124 "|link state\n";
125
126
127 /*
128 * Interface functions
129 */
130
131 /*
132 * Initialize router proc interface.
133 */
134
135 int __init wanrouter_proc_init (void)
136 {
137 struct proc_dir_entry *p;
138 proc_router = proc_mkdir(ROUTER_NAME, proc_net);
139 if (!proc_router)
140 goto fail;
141
142 p = create_proc_entry("config",0,proc_router);
143 if (!p)
144 goto fail_config;
145 p->proc_fops = &router_fops;
146 p->proc_iops = &router_inode;
147 p->get_info = config_get_info;
148 p = create_proc_entry("status",0,proc_router);
149 if (!p)
150 goto fail_stat;
151 p->proc_fops = &router_fops;
152 p->proc_iops = &router_inode;
153 p->get_info = status_get_info;
154 return 0;
155 fail_stat:
156 remove_proc_entry("config", proc_router);
157 fail_config:
158 remove_proc_entry(ROUTER_NAME, proc_net);
159 fail:
160 return -ENOMEM;
161 }
162
163 /*
164 * Clean up router proc interface.
165 */
166
167 void wanrouter_proc_cleanup (void)
168 {
169 remove_proc_entry("config", proc_router);
170 remove_proc_entry("status", proc_router);
171 remove_proc_entry(ROUTER_NAME,proc_net);
172 }
173
174 /*
175 * Add directory entry for WAN device.
176 */
177
178 int wanrouter_proc_add (wan_device_t* wandev)
179 {
180 if (wandev->magic != ROUTER_MAGIC)
181 return -EINVAL;
182
183 wandev->dent = create_proc_entry(wandev->name, 0, proc_router);
184 if (!wandev->dent)
185 return -ENOMEM;
186 wandev->dent->proc_fops = &wandev_fops;
187 wandev->dent->proc_iops = &router_inode;
188 wandev->dent->get_info = wandev_get_info;
189 wandev->dent->data = wandev;
190 return 0;
191 }
192
193 /*
194 * Delete directory entry for WAN device.
195 */
196
197 int wanrouter_proc_delete(wan_device_t* wandev)
198 {
199 if (wandev->magic != ROUTER_MAGIC)
200 return -EINVAL;
201 remove_proc_entry(wandev->name, proc_router);
202 return 0;
203 }
204
205 /****** Proc filesystem entry points ****************************************/
206
207 /*
208 * Verify access rights.
209 */
210
211 static int router_proc_perms (struct inode* inode, int op)
212 {
213 return 0;
214 }
215
216 /*
217 * Read router proc directory entry.
218 * This is universal routine for reading all entries in /proc/net/wanrouter
219 * directory. Each directory entry contains a pointer to the 'method' for
220 * preparing data for that entry.
221 * o verify arguments
222 * o allocate kernel buffer
223 * o call get_info() to prepare data
224 * o copy data to user space
225 * o release kernel buffer
226 *
227 * Return: number of bytes copied to user space (0, if no data)
228 * <0 error
229 */
230
231 static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
232 loff_t *ppos)
233 {
234 struct inode *inode = file->f_dentry->d_inode;
235 struct proc_dir_entry* dent;
236 char* page;
237 int pos, offs, len;
238
239 if (count <= 0)
240 return 0;
241
242 dent = inode->u.generic_ip;
243 if ((dent == NULL) || (dent->get_info == NULL))
244 return 0;
245
246 page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
247 if (page == NULL)
248 return -ENOBUFS;
249
250 pos = dent->get_info(page, dent->data, 0, 0);
251 offs = file->f_pos;
252 if (offs < pos) {
253 len = min(pos - offs, count);
254 if(copy_to_user(buf, (page + offs), len))
255 return -EFAULT;
256 file->f_pos += len;
257 }
258 else
259 len = 0;
260 kfree(page);
261 return len;
262 }
263
264 /*
265 * Prepare data for reading 'Config' entry.
266 * Return length of data.
267 */
268
269 static int config_get_info(char* buf, char** start, off_t offs, int len)
270 {
271 int cnt = sizeof(conf_hdr) - 1;
272 wan_device_t* wandev;
273 strcpy(buf, conf_hdr);
274 for (wandev = router_devlist;
275 wandev && (cnt < (PROC_BUFSZ - 120));
276 wandev = wandev->next) {
277 if (wandev->state) cnt += sprintf(&buf[cnt],
278 "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
279 wandev->name,
280 wandev->ioport,
281 wandev->irq,
282 wandev->dma,
283 wandev->maddr,
284 wandev->msize,
285 wandev->hw_opt[0],
286 wandev->hw_opt[1],
287 wandev->hw_opt[2],
288 wandev->hw_opt[3]);
289 }
290
291 return cnt;
292 }
293
294 /*
295 * Prepare data for reading 'Status' entry.
296 * Return length of data.
297 */
298
299 static int status_get_info(char* buf, char** start, off_t offs, int len)
300 {
301 int cnt = 0;
302 wan_device_t* wandev;
303
304 cnt += sprintf(&buf[cnt], "\nSTATUS FOR PORT 0\n\n");
305 strcpy(&buf[cnt], stat_hdr);
306 cnt += sizeof(stat_hdr) - 1;
307
308 for (wandev = router_devlist;
309 wandev && (cnt < (PROC_BUFSZ - 80));
310 wandev = wandev->next) {
311 if (!wandev->state) continue;
312 cnt += sprintf(&buf[cnt],
313 "%-15s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
314 wandev->name,
315 wandev->station ? " DCE" : " DTE",
316 wandev->interface ? " V.35" : " RS-232",
317 wandev->clocking ? "internal" : "external",
318 wandev->bps,
319 wandev->mtu,
320 wandev->ndev);
321
322 switch (wandev->state) {
323
324 case WAN_UNCONFIGURED:
325 cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
326 break;
327
328 case WAN_DISCONNECTED:
329 cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
330 break;
331
332 case WAN_CONNECTING:
333 cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
334 break;
335
336 case WAN_CONNECTED:
337 cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
338 break;
339
340 default:
341 cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
342 break;
343 }
344 }
345 return cnt;
346 }
347
348 /*
349 * Prepare data for reading <device> entry.
350 * Return length of data.
351 *
352 * On entry, the 'start' argument will contain a pointer to WAN device
353 * data space.
354 */
355
356 static int wandev_get_info(char* buf, char** start, off_t offs, int len)
357 {
358 wan_device_t* wandev = (void*)start;
359 int cnt = 0;
360 int rslt = 0;
361
362 if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
363 return 0;
364 if (!wandev->state)
365 return sprintf(&buf[cnt], "device is not configured!\n");
366
367 /* Update device statistics */
368 if (wandev->update) {
369
370 rslt = wandev->update(wandev);
371 if(rslt) {
372 switch (rslt) {
373 case -EAGAIN:
374 return sprintf(&buf[cnt], "Device is busy!\n");
375
376 default:
377 return sprintf(&buf[cnt],
378 "Device is not configured!\n");
379 }
380 }
381 }
382
383 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
384 "total packets received", wandev->stats.rx_packets);
385 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
386 "total packets transmitted", wandev->stats.tx_packets);
387 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
388 "total bytes received", wandev->stats.rx_bytes);
389 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
390 "total bytes transmitted", wandev->stats.tx_bytes);
391 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
392 "bad packets received", wandev->stats.rx_errors);
393 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
394 "packet transmit problems", wandev->stats.tx_errors);
395 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
396 "received frames dropped", wandev->stats.rx_dropped);
397 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
398 "transmit frames dropped", wandev->stats.tx_dropped);
399 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
400 "multicast packets received", wandev->stats.multicast);
401 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
402 "transmit collisions", wandev->stats.collisions);
403 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
404 "receive length errors", wandev->stats.rx_length_errors);
405 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
406 "receiver overrun errors", wandev->stats.rx_over_errors);
407 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
408 "CRC errors", wandev->stats.rx_crc_errors);
409 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
410 "frame format errors (aborts)", wandev->stats.rx_frame_errors);
411 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
412 "receiver fifo overrun", wandev->stats.rx_fifo_errors);
413 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
414 "receiver missed packet", wandev->stats.rx_missed_errors);
415 cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
416 "aborted frames transmitted", wandev->stats.tx_aborted_errors);
417 return cnt;
418 }
419
420 /*
421 * End
422 */
423
424 #else
425
426 /*
427 * No /proc - output stubs
428 */
429
430 int __init wanrouter_proc_init(void)
431 {
432 return 0;
433 }
434
435 void wanrouter_proc_cleanup(void)
436 {
437 return;
438 }
439
440 int wanrouter_proc_add(wan_device_t *wandev)
441 {
442 return 0;
443 }
444
445 int wanrouter_proc_delete(wan_device_t *wandev)
446 {
447 return 0;
448 }
449
450 #endif
451
452 /*
453 * End
454 */
455
456
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.