Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *      IPX proc routines
  3  *
  4  *      Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002
  5  */
  6 
  7 #include <linux/config.h>
  8 #include <linux/init.h>
  9 #ifdef CONFIG_PROC_FS
 10 #include <linux/proc_fs.h>
 11 #include <linux/spinlock.h>
 12 #include <linux/seq_file.h>
 13 #include <linux/tcp.h>
 14 #include <net/ipx.h>
 15 
 16 static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos)
 17 {
 18         struct ipx_interface *i;
 19 
 20         list_for_each_entry(i, &ipx_interfaces, node)
 21                 if (!pos--)
 22                         goto out;
 23         i = NULL;
 24 out:
 25         return i;
 26 }
 27 
 28 static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i)
 29 {
 30         struct ipx_interface *rc = NULL;
 31 
 32         if (i->node.next != &ipx_interfaces)
 33                 rc = list_entry(i->node.next, struct ipx_interface, node);
 34         return rc;
 35 }
 36 
 37 static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
 38 {
 39         loff_t l = *pos;
 40 
 41         spin_lock_bh(&ipx_interfaces_lock);
 42         return l ? ipx_get_interface_idx(--l) : SEQ_START_TOKEN;
 43 }
 44 
 45 static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
 46 {
 47         struct ipx_interface *i;
 48 
 49         ++*pos;
 50         if (v == SEQ_START_TOKEN)
 51                 i = ipx_interfaces_head();
 52         else
 53                 i = ipx_interfaces_next(v);
 54         return i;
 55 }
 56 
 57 static void ipx_seq_interface_stop(struct seq_file *seq, void *v)
 58 {
 59         spin_unlock_bh(&ipx_interfaces_lock);
 60 }
 61 
 62 static int ipx_seq_interface_show(struct seq_file *seq, void *v)
 63 {
 64         struct ipx_interface *i;
 65 
 66         if (v == SEQ_START_TOKEN) {
 67                 seq_puts(seq, "Network    Node_Address   Primary  Device     "
 68                               "Frame_Type");
 69 #ifdef IPX_REFCNT_DEBUG
 70                 seq_puts(seq, "  refcnt");
 71 #endif
 72                 seq_puts(seq, "\n");
 73                 goto out;
 74         }
 75 
 76         i = v;
 77         seq_printf(seq, "%08lX   ", (unsigned long int)ntohl(i->if_netnum));
 78         seq_printf(seq, "%02X%02X%02X%02X%02X%02X   ",
 79                         i->if_node[0], i->if_node[1], i->if_node[2],
 80                         i->if_node[3], i->if_node[4], i->if_node[5]);
 81         seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No");
 82         seq_printf(seq, "%-11s", ipx_device_name(i));
 83         seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
 84 #ifdef IPX_REFCNT_DEBUG
 85         seq_printf(seq, "%6d", atomic_read(&i->refcnt));
 86 #endif
 87         seq_puts(seq, "\n");
 88 out:
 89         return 0;
 90 }
 91 
 92 static struct ipx_route *ipx_routes_head(void)
 93 {
 94         struct ipx_route *rc = NULL;
 95 
 96         if (!list_empty(&ipx_routes))
 97                 rc = list_entry(ipx_routes.next, struct ipx_route, node);
 98         return rc;
 99 }
100 
101 static struct ipx_route *ipx_routes_next(struct ipx_route *r)
102 {
103         struct ipx_route *rc = NULL;
104 
105         if (r->node.next != &ipx_routes)
106                 rc = list_entry(r->node.next, struct ipx_route, node);
107         return rc;
108 }
109 
110 static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos)
111 {
112         struct ipx_route *r;
113 
114         list_for_each_entry(r, &ipx_routes, node)
115                 if (!pos--)
116                         goto out;
117         r = NULL;
118 out:
119         return r;
120 }
121 
122 static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos)
123 {
124         loff_t l = *pos;
125         read_lock_bh(&ipx_routes_lock);
126         return l ? ipx_get_route_idx(--l) : SEQ_START_TOKEN;
127 }
128 
129 static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
130 {
131         struct ipx_route *r;
132 
133         ++*pos;
134         if (v == SEQ_START_TOKEN)
135                 r = ipx_routes_head();
136         else
137                 r = ipx_routes_next(v);
138         return r;
139 }
140 
141 static void ipx_seq_route_stop(struct seq_file *seq, void *v)
142 {
143         read_unlock_bh(&ipx_routes_lock);
144 }
145 
146 static int ipx_seq_route_show(struct seq_file *seq, void *v)
147 {
148         struct ipx_route *rt;
149 
150         if (v == SEQ_START_TOKEN) {
151                 seq_puts(seq, "Network    Router_Net   Router_Node\n");
152                 goto out;
153         }
154         rt = v;
155         seq_printf(seq, "%08lX   ", (unsigned long int)ntohl(rt->ir_net));
156         if (rt->ir_routed)
157                 seq_printf(seq, "%08lX     %02X%02X%02X%02X%02X%02X\n",
158                            (long unsigned int)ntohl(rt->ir_intrfc->if_netnum),
159                            rt->ir_router_node[0], rt->ir_router_node[1],
160                            rt->ir_router_node[2], rt->ir_router_node[3],
161                            rt->ir_router_node[4], rt->ir_router_node[5]);
162         else
163                 seq_puts(seq, "Directly     Connected\n");
164 out:
165         return 0;
166 }
167 
168 static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
169 {
170         struct sock *s = NULL;
171         struct hlist_node *node;
172         struct ipx_interface *i;
173 
174         list_for_each_entry(i, &ipx_interfaces, node) {
175                 spin_lock_bh(&i->if_sklist_lock);
176                 sk_for_each(s, node, &i->if_sklist) {
177                         if (!pos)
178                                 break;
179                         --pos;
180                 }
181                 spin_unlock_bh(&i->if_sklist_lock);
182                 if (!pos) {
183                         if (node)
184                                 goto found;
185                         break;
186                 }
187         }
188         s = NULL;
189 found:
190         return s;
191 }
192 
193 static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos)
194 {
195         loff_t l = *pos;
196 
197         spin_lock_bh(&ipx_interfaces_lock);
198         return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN;
199 }
200 
201 static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
202 {
203         struct sock* sk, *next;
204         struct ipx_interface *i;
205         struct ipx_sock *ipxs;
206 
207         ++*pos;
208         if (v == SEQ_START_TOKEN) {
209                 sk = NULL;
210                 i = ipx_interfaces_head();
211                 if (!i)
212                         goto out;
213                 sk = sk_head(&i->if_sklist);
214                 if (sk)
215                         spin_lock_bh(&i->if_sklist_lock);
216                 goto out;
217         }
218         sk = v;
219         next = sk_next(sk);
220         if (next) {
221                 sk = next;
222                 goto out;
223         }
224         ipxs = ipx_sk(sk);
225         i = ipxs->intrfc;
226         spin_unlock_bh(&i->if_sklist_lock);
227         sk = NULL;
228         for (;;) {
229                 i = ipx_interfaces_next(i);
230                 if (!i)
231                         break;
232                 spin_lock_bh(&i->if_sklist_lock);
233                 if (!hlist_empty(&i->if_sklist)) {
234                         sk = sk_head(&i->if_sklist);
235                         break;
236                 }
237                 spin_unlock_bh(&i->if_sklist_lock);
238         }
239 out:
240         return sk;
241 }
242 
243 static int ipx_seq_socket_show(struct seq_file *seq, void *v)
244 {
245         struct sock *s;
246         struct ipx_sock *ipxs;
247 
248         if (v == SEQ_START_TOKEN) {
249 #ifdef CONFIG_IPX_INTERN
250                 seq_puts(seq, "Local_Address               "
251                               "Remote_Address              Tx_Queue  "
252                               "Rx_Queue  State  Uid\n");
253 #else
254                 seq_puts(seq, "Local_Address  Remote_Address              "
255                               "Tx_Queue  Rx_Queue  State  Uid\n");
256 #endif
257                 goto out;
258         }
259 
260         s = v;
261         ipxs = ipx_sk(s);
262 #ifdef CONFIG_IPX_INTERN
263         seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
264                    (unsigned long)htonl(ipxs->intrfc->if_netnum),
265                    ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
266                    ipxs->node[4], ipxs->node[5], htons(ipxs->port));
267 #else
268         seq_printf(seq, "%08lX:%04X  ", (unsigned long) htonl(ipxs->intrfc->if_netnum),
269                    htons(ipxs->port));
270 #endif  /* CONFIG_IPX_INTERN */
271         if (s->sk_state != TCP_ESTABLISHED)
272                 seq_printf(seq, "%-28s", "Not_Connected");
273         else {
274                 seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
275                            (unsigned long)htonl(ipxs->dest_addr.net),
276                            ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
277                            ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
278                            ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
279                            htons(ipxs->dest_addr.sock));
280         }
281 
282         seq_printf(seq, "%08X  %08X  %02X     %03d\n",
283                    atomic_read(&s->sk_wmem_alloc),
284                    atomic_read(&s->sk_rmem_alloc),
285                    s->sk_state, SOCK_INODE(s->sk_socket)->i_uid);
286 out:
287         return 0;
288 }
289 
290 static struct seq_operations ipx_seq_interface_ops = {
291         .start  = ipx_seq_interface_start,
292         .next   = ipx_seq_interface_next,
293         .stop   = ipx_seq_interface_stop,
294         .show   = ipx_seq_interface_show,
295 };
296 
297 static struct seq_operations ipx_seq_route_ops = {
298         .start  = ipx_seq_route_start,
299         .next   = ipx_seq_route_next,
300         .stop   = ipx_seq_route_stop,
301         .show   = ipx_seq_route_show,
302 };
303 
304 static struct seq_operations ipx_seq_socket_ops = {
305         .start  = ipx_seq_socket_start,
306         .next   = ipx_seq_socket_next,
307         .stop   = ipx_seq_interface_stop,
308         .show   = ipx_seq_socket_show,
309 };
310 
311 static int ipx_seq_route_open(struct inode *inode, struct file *file)
312 {
313         return seq_open(file, &ipx_seq_route_ops);
314 }
315 
316 static int ipx_seq_interface_open(struct inode *inode, struct file *file)
317 {
318         return seq_open(file, &ipx_seq_interface_ops);
319 }
320 
321 static int ipx_seq_socket_open(struct inode *inode, struct file *file)
322 {
323         return seq_open(file, &ipx_seq_socket_ops);
324 }
325 
326 static struct file_operations ipx_seq_interface_fops = {
327         .owner          = THIS_MODULE,
328         .open           = ipx_seq_interface_open,
329         .read           = seq_read,
330         .llseek         = seq_lseek,
331         .release        = seq_release,
332 };
333 
334 static struct file_operations ipx_seq_route_fops = {
335         .owner          = THIS_MODULE,
336         .open           = ipx_seq_route_open,
337         .read           = seq_read,
338         .llseek         = seq_lseek,
339         .release        = seq_release,
340 };
341 
342 static struct file_operations ipx_seq_socket_fops = {
343         .owner          = THIS_MODULE,
344         .open           = ipx_seq_socket_open,
345         .read           = seq_read,
346         .llseek         = seq_lseek,
347         .release        = seq_release,
348 };
349 
350 static struct proc_dir_entry *ipx_proc_dir;
351 
352 int __init ipx_proc_init(void)
353 {
354         struct proc_dir_entry *p;
355         int rc = -ENOMEM;
356        
357         ipx_proc_dir = proc_mkdir("ipx", proc_net);
358 
359         if (!ipx_proc_dir)
360                 goto out;
361         p = create_proc_entry("interface", S_IRUGO, ipx_proc_dir);
362         if (!p)
363                 goto out_interface;
364 
365         p->proc_fops = &ipx_seq_interface_fops;
366         p = create_proc_entry("route", S_IRUGO, ipx_proc_dir);
367         if (!p)
368                 goto out_route;
369 
370         p->proc_fops = &ipx_seq_route_fops;
371         p = create_proc_entry("socket", S_IRUGO, ipx_proc_dir);
372         if (!p)
373                 goto out_socket;
374 
375         p->proc_fops = &ipx_seq_socket_fops;
376 
377         rc = 0;
378 out:
379         return rc;
380 out_socket:
381         remove_proc_entry("route", ipx_proc_dir);
382 out_route:
383         remove_proc_entry("interface", ipx_proc_dir);
384 out_interface:
385         remove_proc_entry("ipx", proc_net);
386         goto out;
387 }
388 
389 void __exit ipx_proc_exit(void)
390 {
391         remove_proc_entry("interface", ipx_proc_dir);
392         remove_proc_entry("route", ipx_proc_dir);
393         remove_proc_entry("socket", ipx_proc_dir);
394         remove_proc_entry("ipx", proc_net);
395 }
396 
397 #else /* CONFIG_PROC_FS */
398 
399 int __init ipx_proc_init(void)
400 {
401         return 0;
402 }
403 
404 void __exit ipx_proc_exit(void)
405 {
406 }
407 
408 #endif /* CONFIG_PROC_FS */
409 
  This page was automatically generated by the LXR engine.