• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/init.h>		/* __initfunc et al. */
24 #include <linux/stddef.h>	/* offsetof(), etc. */
25 #include <linux/errno.h>	/* return codes */
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/wanrouter.h>	/* WAN router API definitions */
29 #include <linux/seq_file.h>
30 #include <linux/smp_lock.h>
31 
32 #include <net/net_namespace.h>
33 #include <asm/io.h>
34 
35 #define PROC_STATS_FORMAT "%30s: %12lu\n"
36 
37 /****** Defines and Macros **************************************************/
38 
39 #define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
40 			      (prot == WANCONFIG_X25) ? " X25" : \
41 				 (prot == WANCONFIG_PPP) ? " PPP" : \
42 				    (prot == WANCONFIG_CHDLC) ? " CHDLC": \
43 				       (prot == WANCONFIG_MPPP) ? " MPPP" : \
44 					   " Unknown" )
45 
46 /****** Function Prototypes *************************************************/
47 
48 #ifdef CONFIG_PROC_FS
49 
50 /* Miscellaneous */
51 
52 /*
53  *	Structures for interfacing with the /proc filesystem.
54  *	Router creates its own directory /proc/net/router with the folowing
55  *	entries:
56  *	config		device configuration
57  *	status		global device statistics
58  *	<device>	entry for each WAN device
59  */
60 
61 /*
62  *	Generic /proc/net/router/<file> file and inode operations
63  */
64 
65 /*
66  *	/proc/net/router
67  */
68 
69 static struct proc_dir_entry *proc_router;
70 
71 /* Strings */
72 
73 /*
74  *	Interface functions
75  */
76 
77 /****** Proc filesystem entry points ****************************************/
78 
79 /*
80  *	Iterator
81  */
r_start(struct seq_file * m,loff_t * pos)82 static void *r_start(struct seq_file *m, loff_t *pos)
83 {
84 	struct wan_device *wandev;
85 	loff_t l = *pos;
86 
87 	lock_kernel();
88 	if (!l--)
89 		return SEQ_START_TOKEN;
90 	for (wandev = wanrouter_router_devlist; l-- && wandev;
91 	     wandev = wandev->next)
92 		;
93 	return wandev;
94 }
95 
r_next(struct seq_file * m,void * v,loff_t * pos)96 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
97 {
98 	struct wan_device *wandev = v;
99 	(*pos)++;
100 	return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
101 }
102 
r_stop(struct seq_file * m,void * v)103 static void r_stop(struct seq_file *m, void *v)
104 {
105 	unlock_kernel();
106 }
107 
config_show(struct seq_file * m,void * v)108 static int config_show(struct seq_file *m, void *v)
109 {
110 	struct wan_device *p = v;
111 	if (v == SEQ_START_TOKEN) {
112 		seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |"
113 			    "mem.size|option1|option2|option3|option4\n");
114 		return 0;
115 	}
116 	if (!p->state)
117 		return 0;
118 	seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
119 			p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
120 			p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
121 	return 0;
122 }
123 
status_show(struct seq_file * m,void * v)124 static int status_show(struct seq_file *m, void *v)
125 {
126 	struct wan_device *p = v;
127 	if (v == SEQ_START_TOKEN) {
128 		seq_puts(m, "Device name    |protocol|station|interface|"
129 			    "clocking|baud rate| MTU |ndev|link state\n");
130 		return 0;
131 	}
132 	if (!p->state)
133 		return 0;
134 	seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
135 		p->name,
136 		PROT_DECODE(p->config_id),
137 		p->config_id == WANCONFIG_FR ?
138 			(p->station ? "Node" : "CPE") :
139 			(p->config_id == WANCONFIG_X25 ?
140 			(p->station ? "DCE" : "DTE") :
141 			("N/A")),
142 		p->interface ? "V.35" : "RS-232",
143 		p->clocking ? "internal" : "external",
144 		p->bps,
145 		p->mtu,
146 		p->ndev);
147 
148 	switch (p->state) {
149 	case WAN_UNCONFIGURED:
150 		seq_printf(m, "%-12s\n", "unconfigured");
151 		break;
152 	case WAN_DISCONNECTED:
153 		seq_printf(m, "%-12s\n", "disconnected");
154 		break;
155 	case WAN_CONNECTING:
156 		seq_printf(m, "%-12s\n", "connecting");
157 		break;
158 	case WAN_CONNECTED:
159 		seq_printf(m, "%-12s\n", "connected");
160 		break;
161 	default:
162 		seq_printf(m, "%-12s\n", "invalid");
163 		break;
164 	}
165 	return 0;
166 }
167 
168 static const struct seq_operations config_op = {
169 	.start	= r_start,
170 	.next	= r_next,
171 	.stop	= r_stop,
172 	.show	= config_show,
173 };
174 
175 static const struct seq_operations status_op = {
176 	.start	= r_start,
177 	.next	= r_next,
178 	.stop	= r_stop,
179 	.show	= status_show,
180 };
181 
config_open(struct inode * inode,struct file * file)182 static int config_open(struct inode *inode, struct file *file)
183 {
184 	return seq_open(file, &config_op);
185 }
186 
status_open(struct inode * inode,struct file * file)187 static int status_open(struct inode *inode, struct file *file)
188 {
189 	return seq_open(file, &status_op);
190 }
191 
192 static const struct file_operations config_fops = {
193 	.owner	 = THIS_MODULE,
194 	.open	 = config_open,
195 	.read	 = seq_read,
196 	.llseek	 = seq_lseek,
197 	.release = seq_release,
198 };
199 
200 static const struct file_operations status_fops = {
201 	.owner	 = THIS_MODULE,
202 	.open	 = status_open,
203 	.read	 = seq_read,
204 	.llseek	 = seq_lseek,
205 	.release = seq_release,
206 };
207 
wandev_show(struct seq_file * m,void * v)208 static int wandev_show(struct seq_file *m, void *v)
209 {
210 	struct wan_device *wandev = m->private;
211 
212 	if (wandev->magic != ROUTER_MAGIC)
213 		return 0;
214 
215 	if (!wandev->state) {
216 		seq_puts(m, "device is not configured!\n");
217 		return 0;
218 	}
219 
220 	/* Update device statistics */
221 	if (wandev->update) {
222 		int err = wandev->update(wandev);
223 		if (err == -EAGAIN) {
224 			seq_puts(m, "Device is busy!\n");
225 			return 0;
226 		}
227 		if (err) {
228 			seq_puts(m, "Device is not configured!\n");
229 			return 0;
230 		}
231 	}
232 
233 	seq_printf(m, PROC_STATS_FORMAT,
234 		"total packets received", wandev->stats.rx_packets);
235 	seq_printf(m, PROC_STATS_FORMAT,
236 		"total packets transmitted", wandev->stats.tx_packets);
237 	seq_printf(m, PROC_STATS_FORMAT,
238 		"total bytes received", wandev->stats.rx_bytes);
239 	seq_printf(m, PROC_STATS_FORMAT,
240 		"total bytes transmitted", wandev->stats.tx_bytes);
241 	seq_printf(m, PROC_STATS_FORMAT,
242 		"bad packets received", wandev->stats.rx_errors);
243 	seq_printf(m, PROC_STATS_FORMAT,
244 		"packet transmit problems", wandev->stats.tx_errors);
245 	seq_printf(m, PROC_STATS_FORMAT,
246 		"received frames dropped", wandev->stats.rx_dropped);
247 	seq_printf(m, PROC_STATS_FORMAT,
248 		"transmit frames dropped", wandev->stats.tx_dropped);
249 	seq_printf(m, PROC_STATS_FORMAT,
250 		"multicast packets received", wandev->stats.multicast);
251 	seq_printf(m, PROC_STATS_FORMAT,
252 		"transmit collisions", wandev->stats.collisions);
253 	seq_printf(m, PROC_STATS_FORMAT,
254 		"receive length errors", wandev->stats.rx_length_errors);
255 	seq_printf(m, PROC_STATS_FORMAT,
256 		"receiver overrun errors", wandev->stats.rx_over_errors);
257 	seq_printf(m, PROC_STATS_FORMAT,
258 		"CRC errors", wandev->stats.rx_crc_errors);
259 	seq_printf(m, PROC_STATS_FORMAT,
260 		"frame format errors (aborts)", wandev->stats.rx_frame_errors);
261 	seq_printf(m, PROC_STATS_FORMAT,
262 		"receiver fifo overrun", wandev->stats.rx_fifo_errors);
263 	seq_printf(m, PROC_STATS_FORMAT,
264 		"receiver missed packet", wandev->stats.rx_missed_errors);
265 	seq_printf(m, PROC_STATS_FORMAT,
266 		"aborted frames transmitted", wandev->stats.tx_aborted_errors);
267 	return 0;
268 }
269 
wandev_open(struct inode * inode,struct file * file)270 static int wandev_open(struct inode *inode, struct file *file)
271 {
272 	return single_open(file, wandev_show, PDE(inode)->data);
273 }
274 
275 static const struct file_operations wandev_fops = {
276 	.owner	 = THIS_MODULE,
277 	.open	 = wandev_open,
278 	.read	 = seq_read,
279 	.llseek	 = seq_lseek,
280 	.release = single_release,
281 	.unlocked_ioctl  = wanrouter_ioctl,
282 };
283 
284 /*
285  *	Initialize router proc interface.
286  */
287 
wanrouter_proc_init(void)288 int __init wanrouter_proc_init(void)
289 {
290 	struct proc_dir_entry *p;
291 	proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
292 	if (!proc_router)
293 		goto fail;
294 
295 	p = proc_create("config", S_IRUGO, proc_router, &config_fops);
296 	if (!p)
297 		goto fail_config;
298 	p = proc_create("status", S_IRUGO, proc_router, &status_fops);
299 	if (!p)
300 		goto fail_stat;
301 	return 0;
302 fail_stat:
303 	remove_proc_entry("config", proc_router);
304 fail_config:
305 	remove_proc_entry(ROUTER_NAME, init_net.proc_net);
306 fail:
307 	return -ENOMEM;
308 }
309 
310 /*
311  *	Clean up router proc interface.
312  */
313 
wanrouter_proc_cleanup(void)314 void wanrouter_proc_cleanup(void)
315 {
316 	remove_proc_entry("config", proc_router);
317 	remove_proc_entry("status", proc_router);
318 	remove_proc_entry(ROUTER_NAME, init_net.proc_net);
319 }
320 
321 /*
322  *	Add directory entry for WAN device.
323  */
324 
wanrouter_proc_add(struct wan_device * wandev)325 int wanrouter_proc_add(struct wan_device* wandev)
326 {
327 	if (wandev->magic != ROUTER_MAGIC)
328 		return -EINVAL;
329 
330 	wandev->dent = proc_create(wandev->name, S_IRUGO,
331 				   proc_router, &wandev_fops);
332 	if (!wandev->dent)
333 		return -ENOMEM;
334 	wandev->dent->data	= wandev;
335 	return 0;
336 }
337 
338 /*
339  *	Delete directory entry for WAN device.
340  */
wanrouter_proc_delete(struct wan_device * wandev)341 int wanrouter_proc_delete(struct wan_device* wandev)
342 {
343 	if (wandev->magic != ROUTER_MAGIC)
344 		return -EINVAL;
345 	remove_proc_entry(wandev->name, proc_router);
346 	return 0;
347 }
348 
349 #else
350 
351 /*
352  *	No /proc - output stubs
353  */
354 
wanrouter_proc_init(void)355 int __init wanrouter_proc_init(void)
356 {
357 	return 0;
358 }
359 
wanrouter_proc_cleanup(void)360 void wanrouter_proc_cleanup(void)
361 {
362 }
363 
wanrouter_proc_add(struct wan_device * wandev)364 int wanrouter_proc_add(struct wan_device *wandev)
365 {
366 	return 0;
367 }
368 
wanrouter_proc_delete(struct wan_device * wandev)369 int wanrouter_proc_delete(struct wan_device *wandev)
370 {
371 	return 0;
372 }
373 
374 #endif
375 
376 /*
377  *	End
378  */
379 
380