Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wanproc.c
Go to the documentation of this file.
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/mutex.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 following
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 DEFINE_MUTEX(config_mutex);
70 static struct proc_dir_entry *proc_router;
71 
72 /* Strings */
73 
74 /*
75  * Interface functions
76  */
77 
78 /****** Proc filesystem entry points ****************************************/
79 
80 /*
81  * Iterator
82  */
83 static void *r_start(struct seq_file *m, loff_t *pos)
84 {
85  struct wan_device *wandev;
86  loff_t l = *pos;
87 
88  mutex_lock(&config_mutex);
89  if (!l--)
90  return SEQ_START_TOKEN;
91  for (wandev = wanrouter_router_devlist; l-- && wandev;
92  wandev = wandev->next)
93  ;
94  return wandev;
95 }
96 
97 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
98 {
99  struct wan_device *wandev = v;
100  (*pos)++;
101  return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
102 }
103 
104 static void r_stop(struct seq_file *m, void *v)
105 {
106  mutex_unlock(&config_mutex);
107 }
108 
109 static int config_show(struct seq_file *m, void *v)
110 {
111  struct wan_device *p = v;
112  if (v == SEQ_START_TOKEN) {
113  seq_puts(m, "Device name | port |IRQ|DMA| mem.addr |"
114  "mem.size|option1|option2|option3|option4\n");
115  return 0;
116  }
117  if (!p->state)
118  return 0;
119  seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
120  p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
121  p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
122  return 0;
123 }
124 
125 static int status_show(struct seq_file *m, void *v)
126 {
127  struct wan_device *p = v;
128  if (v == SEQ_START_TOKEN) {
129  seq_puts(m, "Device name |protocol|station|interface|"
130  "clocking|baud rate| MTU |ndev|link state\n");
131  return 0;
132  }
133  if (!p->state)
134  return 0;
135  seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
136  p->name,
138  p->config_id == WANCONFIG_FR ?
139  (p->station ? "Node" : "CPE") :
140  (p->config_id == WANCONFIG_X25 ?
141  (p->station ? "DCE" : "DTE") :
142  ("N/A")),
143  p->interface ? "V.35" : "RS-232",
144  p->clocking ? "internal" : "external",
145  p->bps,
146  p->mtu,
147  p->ndev);
148 
149  switch (p->state) {
150  case WAN_UNCONFIGURED:
151  seq_printf(m, "%-12s\n", "unconfigured");
152  break;
153  case WAN_DISCONNECTED:
154  seq_printf(m, "%-12s\n", "disconnected");
155  break;
156  case WAN_CONNECTING:
157  seq_printf(m, "%-12s\n", "connecting");
158  break;
159  case WAN_CONNECTED:
160  seq_printf(m, "%-12s\n", "connected");
161  break;
162  default:
163  seq_printf(m, "%-12s\n", "invalid");
164  break;
165  }
166  return 0;
167 }
168 
169 static const struct seq_operations config_op = {
170  .start = r_start,
171  .next = r_next,
172  .stop = r_stop,
173  .show = config_show,
174 };
175 
176 static const struct seq_operations status_op = {
177  .start = r_start,
178  .next = r_next,
179  .stop = r_stop,
180  .show = status_show,
181 };
182 
183 static int config_open(struct inode *inode, struct file *file)
184 {
185  return seq_open(file, &config_op);
186 }
187 
188 static int status_open(struct inode *inode, struct file *file)
189 {
190  return seq_open(file, &status_op);
191 }
192 
193 static const struct file_operations config_fops = {
194  .owner = THIS_MODULE,
195  .open = config_open,
196  .read = seq_read,
197  .llseek = seq_lseek,
198  .release = seq_release,
199 };
200 
201 static const struct file_operations status_fops = {
202  .owner = THIS_MODULE,
203  .open = status_open,
204  .read = seq_read,
205  .llseek = seq_lseek,
206  .release = seq_release,
207 };
208 
209 static int wandev_show(struct seq_file *m, void *v)
210 {
211  struct wan_device *wandev = m->private;
212 
213  if (wandev->magic != ROUTER_MAGIC)
214  return 0;
215 
216  if (!wandev->state) {
217  seq_puts(m, "device is not configured!\n");
218  return 0;
219  }
220 
221  /* Update device statistics */
222  if (wandev->update) {
223  int err = wandev->update(wandev);
224  if (err == -EAGAIN) {
225  seq_puts(m, "Device is busy!\n");
226  return 0;
227  }
228  if (err) {
229  seq_puts(m, "Device is not configured!\n");
230  return 0;
231  }
232  }
233 
235  "total packets received", wandev->stats.rx_packets);
237  "total packets transmitted", wandev->stats.tx_packets);
239  "total bytes received", wandev->stats.rx_bytes);
241  "total bytes transmitted", wandev->stats.tx_bytes);
243  "bad packets received", wandev->stats.rx_errors);
245  "packet transmit problems", wandev->stats.tx_errors);
247  "received frames dropped", wandev->stats.rx_dropped);
249  "transmit frames dropped", wandev->stats.tx_dropped);
251  "multicast packets received", wandev->stats.multicast);
253  "transmit collisions", wandev->stats.collisions);
255  "receive length errors", wandev->stats.rx_length_errors);
257  "receiver overrun errors", wandev->stats.rx_over_errors);
259  "CRC errors", wandev->stats.rx_crc_errors);
261  "frame format errors (aborts)", wandev->stats.rx_frame_errors);
263  "receiver fifo overrun", wandev->stats.rx_fifo_errors);
265  "receiver missed packet", wandev->stats.rx_missed_errors);
267  "aborted frames transmitted", wandev->stats.tx_aborted_errors);
268  return 0;
269 }
270 
271 static int wandev_open(struct inode *inode, struct file *file)
272 {
273  return single_open(file, wandev_show, PDE(inode)->data);
274 }
275 
276 static const struct file_operations wandev_fops = {
277  .owner = THIS_MODULE,
278  .open = wandev_open,
279  .read = seq_read,
280  .llseek = seq_lseek,
281  .release = single_release,
282  .unlocked_ioctl = wanrouter_ioctl,
283 };
284 
285 /*
286  * Initialize router proc interface.
287  */
288 
289 int __init wanrouter_proc_init(void)
290 {
291  struct proc_dir_entry *p;
292  proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
293  if (!proc_router)
294  goto fail;
295 
296  p = proc_create("config", S_IRUGO, proc_router, &config_fops);
297  if (!p)
298  goto fail_config;
299  p = proc_create("status", S_IRUGO, proc_router, &status_fops);
300  if (!p)
301  goto fail_stat;
302  return 0;
303 fail_stat:
304  remove_proc_entry("config", proc_router);
305 fail_config:
307 fail:
308  return -ENOMEM;
309 }
310 
311 /*
312  * Clean up router proc interface.
313  */
314 
315 void wanrouter_proc_cleanup(void)
316 {
317  remove_proc_entry("config", proc_router);
318  remove_proc_entry("status", proc_router);
320 }
321 
322 /*
323  * Add directory entry for WAN device.
324  */
325 
326 int wanrouter_proc_add(struct wan_device* wandev)
327 {
328  if (wandev->magic != ROUTER_MAGIC)
329  return -EINVAL;
330 
331  wandev->dent = proc_create(wandev->name, S_IRUGO,
332  proc_router, &wandev_fops);
333  if (!wandev->dent)
334  return -ENOMEM;
335  wandev->dent->data = wandev;
336  return 0;
337 }
338 
339 /*
340  * Delete directory entry for WAN device.
341  */
342 int wanrouter_proc_delete(struct wan_device* wandev)
343 {
344  if (wandev->magic != ROUTER_MAGIC)
345  return -EINVAL;
346  remove_proc_entry(wandev->name, proc_router);
347  return 0;
348 }
349 
350 #else
351 
352 /*
353  * No /proc - output stubs
354  */
355 
357 {
358  return 0;
359 }
360 
362 {
363 }
364 
365 int wanrouter_proc_add(struct wan_device *wandev)
366 {
367  return 0;
368 }
369 
371 {
372  return 0;
373 }
374 
375 #endif
376 
377 /*
378  * End
379  */
380