Root/
1 | /* |
2 | * IPX proc routines |
3 | * |
4 | * Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002 |
5 | */ |
6 | |
7 | #include <linux/init.h> |
8 | #ifdef CONFIG_PROC_FS |
9 | #include <linux/proc_fs.h> |
10 | #include <linux/spinlock.h> |
11 | #include <linux/seq_file.h> |
12 | #include <net/net_namespace.h> |
13 | #include <net/tcp_states.h> |
14 | #include <net/ipx.h> |
15 | |
16 | static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) |
17 | { |
18 | spin_lock_bh(&ipx_interfaces_lock); |
19 | return seq_list_start_head(&ipx_interfaces, *pos); |
20 | } |
21 | |
22 | static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) |
23 | { |
24 | return seq_list_next(v, &ipx_interfaces, pos); |
25 | } |
26 | |
27 | static void ipx_seq_interface_stop(struct seq_file *seq, void *v) |
28 | { |
29 | spin_unlock_bh(&ipx_interfaces_lock); |
30 | } |
31 | |
32 | static int ipx_seq_interface_show(struct seq_file *seq, void *v) |
33 | { |
34 | struct ipx_interface *i; |
35 | |
36 | if (v == &ipx_interfaces) { |
37 | seq_puts(seq, "Network Node_Address Primary Device " |
38 | "Frame_Type"); |
39 | #ifdef IPX_REFCNT_DEBUG |
40 | seq_puts(seq, " refcnt"); |
41 | #endif |
42 | seq_puts(seq, "\n"); |
43 | goto out; |
44 | } |
45 | |
46 | i = list_entry(v, struct ipx_interface, node); |
47 | seq_printf(seq, "%08lX ", (unsigned long int)ntohl(i->if_netnum)); |
48 | seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", |
49 | i->if_node[0], i->if_node[1], i->if_node[2], |
50 | i->if_node[3], i->if_node[4], i->if_node[5]); |
51 | seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No"); |
52 | seq_printf(seq, "%-11s", ipx_device_name(i)); |
53 | seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type)); |
54 | #ifdef IPX_REFCNT_DEBUG |
55 | seq_printf(seq, "%6d", atomic_read(&i->refcnt)); |
56 | #endif |
57 | seq_puts(seq, "\n"); |
58 | out: |
59 | return 0; |
60 | } |
61 | |
62 | static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) |
63 | { |
64 | read_lock_bh(&ipx_routes_lock); |
65 | return seq_list_start_head(&ipx_routes, *pos); |
66 | } |
67 | |
68 | static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) |
69 | { |
70 | return seq_list_next(v, &ipx_routes, pos); |
71 | } |
72 | |
73 | static void ipx_seq_route_stop(struct seq_file *seq, void *v) |
74 | { |
75 | read_unlock_bh(&ipx_routes_lock); |
76 | } |
77 | |
78 | static int ipx_seq_route_show(struct seq_file *seq, void *v) |
79 | { |
80 | struct ipx_route *rt; |
81 | |
82 | if (v == &ipx_routes) { |
83 | seq_puts(seq, "Network Router_Net Router_Node\n"); |
84 | goto out; |
85 | } |
86 | |
87 | rt = list_entry(v, struct ipx_route, node); |
88 | |
89 | seq_printf(seq, "%08lX ", (unsigned long int)ntohl(rt->ir_net)); |
90 | if (rt->ir_routed) |
91 | seq_printf(seq, "%08lX %02X%02X%02X%02X%02X%02X\n", |
92 | (long unsigned int)ntohl(rt->ir_intrfc->if_netnum), |
93 | rt->ir_router_node[0], rt->ir_router_node[1], |
94 | rt->ir_router_node[2], rt->ir_router_node[3], |
95 | rt->ir_router_node[4], rt->ir_router_node[5]); |
96 | else |
97 | seq_puts(seq, "Directly Connected\n"); |
98 | out: |
99 | return 0; |
100 | } |
101 | |
102 | static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) |
103 | { |
104 | struct sock *s = NULL; |
105 | struct hlist_node *node; |
106 | struct ipx_interface *i; |
107 | |
108 | list_for_each_entry(i, &ipx_interfaces, node) { |
109 | spin_lock_bh(&i->if_sklist_lock); |
110 | sk_for_each(s, node, &i->if_sklist) { |
111 | if (!pos) |
112 | break; |
113 | --pos; |
114 | } |
115 | spin_unlock_bh(&i->if_sklist_lock); |
116 | if (!pos) { |
117 | if (node) |
118 | goto found; |
119 | break; |
120 | } |
121 | } |
122 | s = NULL; |
123 | found: |
124 | return s; |
125 | } |
126 | |
127 | static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos) |
128 | { |
129 | loff_t l = *pos; |
130 | |
131 | spin_lock_bh(&ipx_interfaces_lock); |
132 | return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN; |
133 | } |
134 | |
135 | static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) |
136 | { |
137 | struct sock* sk, *next; |
138 | struct ipx_interface *i; |
139 | struct ipx_sock *ipxs; |
140 | |
141 | ++*pos; |
142 | if (v == SEQ_START_TOKEN) { |
143 | sk = NULL; |
144 | i = ipx_interfaces_head(); |
145 | if (!i) |
146 | goto out; |
147 | sk = sk_head(&i->if_sklist); |
148 | if (sk) |
149 | spin_lock_bh(&i->if_sklist_lock); |
150 | goto out; |
151 | } |
152 | sk = v; |
153 | next = sk_next(sk); |
154 | if (next) { |
155 | sk = next; |
156 | goto out; |
157 | } |
158 | ipxs = ipx_sk(sk); |
159 | i = ipxs->intrfc; |
160 | spin_unlock_bh(&i->if_sklist_lock); |
161 | sk = NULL; |
162 | for (;;) { |
163 | if (i->node.next == &ipx_interfaces) |
164 | break; |
165 | i = list_entry(i->node.next, struct ipx_interface, node); |
166 | spin_lock_bh(&i->if_sklist_lock); |
167 | if (!hlist_empty(&i->if_sklist)) { |
168 | sk = sk_head(&i->if_sklist); |
169 | break; |
170 | } |
171 | spin_unlock_bh(&i->if_sklist_lock); |
172 | } |
173 | out: |
174 | return sk; |
175 | } |
176 | |
177 | static int ipx_seq_socket_show(struct seq_file *seq, void *v) |
178 | { |
179 | struct sock *s; |
180 | struct ipx_sock *ipxs; |
181 | |
182 | if (v == SEQ_START_TOKEN) { |
183 | #ifdef CONFIG_IPX_INTERN |
184 | seq_puts(seq, "Local_Address " |
185 | "Remote_Address Tx_Queue " |
186 | "Rx_Queue State Uid\n"); |
187 | #else |
188 | seq_puts(seq, "Local_Address Remote_Address " |
189 | "Tx_Queue Rx_Queue State Uid\n"); |
190 | #endif |
191 | goto out; |
192 | } |
193 | |
194 | s = v; |
195 | ipxs = ipx_sk(s); |
196 | #ifdef CONFIG_IPX_INTERN |
197 | seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", |
198 | (unsigned long)ntohl(ipxs->intrfc->if_netnum), |
199 | ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3], |
200 | ipxs->node[4], ipxs->node[5], ntohs(ipxs->port)); |
201 | #else |
202 | seq_printf(seq, "%08lX:%04X ", (unsigned long) ntohl(ipxs->intrfc->if_netnum), |
203 | ntohs(ipxs->port)); |
204 | #endif /* CONFIG_IPX_INTERN */ |
205 | if (s->sk_state != TCP_ESTABLISHED) |
206 | seq_printf(seq, "%-28s", "Not_Connected"); |
207 | else { |
208 | seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", |
209 | (unsigned long)ntohl(ipxs->dest_addr.net), |
210 | ipxs->dest_addr.node[0], ipxs->dest_addr.node[1], |
211 | ipxs->dest_addr.node[2], ipxs->dest_addr.node[3], |
212 | ipxs->dest_addr.node[4], ipxs->dest_addr.node[5], |
213 | ntohs(ipxs->dest_addr.sock)); |
214 | } |
215 | |
216 | seq_printf(seq, "%08X %08X %02X %03d\n", |
217 | sk_wmem_alloc_get(s), |
218 | sk_rmem_alloc_get(s), |
219 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); |
220 | out: |
221 | return 0; |
222 | } |
223 | |
224 | static const struct seq_operations ipx_seq_interface_ops = { |
225 | .start = ipx_seq_interface_start, |
226 | .next = ipx_seq_interface_next, |
227 | .stop = ipx_seq_interface_stop, |
228 | .show = ipx_seq_interface_show, |
229 | }; |
230 | |
231 | static const struct seq_operations ipx_seq_route_ops = { |
232 | .start = ipx_seq_route_start, |
233 | .next = ipx_seq_route_next, |
234 | .stop = ipx_seq_route_stop, |
235 | .show = ipx_seq_route_show, |
236 | }; |
237 | |
238 | static const struct seq_operations ipx_seq_socket_ops = { |
239 | .start = ipx_seq_socket_start, |
240 | .next = ipx_seq_socket_next, |
241 | .stop = ipx_seq_interface_stop, |
242 | .show = ipx_seq_socket_show, |
243 | }; |
244 | |
245 | static int ipx_seq_route_open(struct inode *inode, struct file *file) |
246 | { |
247 | return seq_open(file, &ipx_seq_route_ops); |
248 | } |
249 | |
250 | static int ipx_seq_interface_open(struct inode *inode, struct file *file) |
251 | { |
252 | return seq_open(file, &ipx_seq_interface_ops); |
253 | } |
254 | |
255 | static int ipx_seq_socket_open(struct inode *inode, struct file *file) |
256 | { |
257 | return seq_open(file, &ipx_seq_socket_ops); |
258 | } |
259 | |
260 | static const struct file_operations ipx_seq_interface_fops = { |
261 | .owner = THIS_MODULE, |
262 | .open = ipx_seq_interface_open, |
263 | .read = seq_read, |
264 | .llseek = seq_lseek, |
265 | .release = seq_release, |
266 | }; |
267 | |
268 | static const struct file_operations ipx_seq_route_fops = { |
269 | .owner = THIS_MODULE, |
270 | .open = ipx_seq_route_open, |
271 | .read = seq_read, |
272 | .llseek = seq_lseek, |
273 | .release = seq_release, |
274 | }; |
275 | |
276 | static const struct file_operations ipx_seq_socket_fops = { |
277 | .owner = THIS_MODULE, |
278 | .open = ipx_seq_socket_open, |
279 | .read = seq_read, |
280 | .llseek = seq_lseek, |
281 | .release = seq_release, |
282 | }; |
283 | |
284 | static struct proc_dir_entry *ipx_proc_dir; |
285 | |
286 | int __init ipx_proc_init(void) |
287 | { |
288 | struct proc_dir_entry *p; |
289 | int rc = -ENOMEM; |
290 | |
291 | ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net); |
292 | |
293 | if (!ipx_proc_dir) |
294 | goto out; |
295 | p = proc_create("interface", S_IRUGO, |
296 | ipx_proc_dir, &ipx_seq_interface_fops); |
297 | if (!p) |
298 | goto out_interface; |
299 | |
300 | p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops); |
301 | if (!p) |
302 | goto out_route; |
303 | |
304 | p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops); |
305 | if (!p) |
306 | goto out_socket; |
307 | |
308 | rc = 0; |
309 | out: |
310 | return rc; |
311 | out_socket: |
312 | remove_proc_entry("route", ipx_proc_dir); |
313 | out_route: |
314 | remove_proc_entry("interface", ipx_proc_dir); |
315 | out_interface: |
316 | remove_proc_entry("ipx", init_net.proc_net); |
317 | goto out; |
318 | } |
319 | |
320 | void __exit ipx_proc_exit(void) |
321 | { |
322 | remove_proc_entry("interface", ipx_proc_dir); |
323 | remove_proc_entry("route", ipx_proc_dir); |
324 | remove_proc_entry("socket", ipx_proc_dir); |
325 | remove_proc_entry("ipx", init_net.proc_net); |
326 | } |
327 | |
328 | #else /* CONFIG_PROC_FS */ |
329 | |
330 | int __init ipx_proc_init(void) |
331 | { |
332 | return 0; |
333 | } |
334 | |
335 | void __exit ipx_proc_exit(void) |
336 | { |
337 | } |
338 | |
339 | #endif /* CONFIG_PROC_FS */ |
340 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9