1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/init.h>
24#include <linux/stddef.h>
25#include <linux/errno.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/wanrouter.h>
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
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
47
48#ifdef CONFIG_PROC_FS
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69static struct proc_dir_entry *proc_router;
70
71
72
73
74
75
76
77
78
79
80
81
82static 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
96static 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
103static void r_stop(struct seq_file *m, void *v)
104{
105 unlock_kernel();
106}
107
108static 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
124static 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
168static const struct seq_operations config_op = {
169 .start = r_start,
170 .next = r_next,
171 .stop = r_stop,
172 .show = config_show,
173};
174
175static const struct seq_operations status_op = {
176 .start = r_start,
177 .next = r_next,
178 .stop = r_stop,
179 .show = status_show,
180};
181
182static int config_open(struct inode *inode, struct file *file)
183{
184 return seq_open(file, &config_op);
185}
186
187static int status_open(struct inode *inode, struct file *file)
188{
189 return seq_open(file, &status_op);
190}
191
192static 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
200static 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
208static 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
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
270static int wandev_open(struct inode *inode, struct file *file)
271{
272 return single_open(file, wandev_show, PDE(inode)->data);
273}
274
275static 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
286
287
288int __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;
302fail_stat:
303 remove_proc_entry("config", proc_router);
304fail_config:
305 remove_proc_entry(ROUTER_NAME, init_net.proc_net);
306fail:
307 return -ENOMEM;
308}
309
310
311
312
313
314void 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
323
324
325int 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
340
341int 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
353
354
355int __init wanrouter_proc_init(void)
356{
357 return 0;
358}
359
360void wanrouter_proc_cleanup(void)
361{
362}
363
364int wanrouter_proc_add(struct wan_device *wandev)
365{
366 return 0;
367}
368
369int wanrouter_proc_delete(struct wan_device *wandev)
370{
371 return 0;
372}
373
374#endif
375
376
377
378
379
380