2 * atalk_proc.c - proc support for Appletalk
4 * Copyright(c) Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, version 2.
11 #include <linux/init.h>
12 #include <linux/proc_fs.h>
13 #include <linux/seq_file.h>
14 #include <net/net_namespace.h>
16 #include <linux/atalk.h>
19 static __inline__
struct atalk_iface
*atalk_get_interface_idx(loff_t pos
)
21 struct atalk_iface
*i
;
23 for (i
= atalk_interfaces
; pos
&& i
; i
= i
->next
)
29 static void *atalk_seq_interface_start(struct seq_file
*seq
, loff_t
*pos
)
30 __acquires(atalk_interfaces_lock
)
34 read_lock_bh(&atalk_interfaces_lock
);
35 return l
? atalk_get_interface_idx(--l
) : SEQ_START_TOKEN
;
38 static void *atalk_seq_interface_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
40 struct atalk_iface
*i
;
43 if (v
== SEQ_START_TOKEN
) {
55 static void atalk_seq_interface_stop(struct seq_file
*seq
, void *v
)
56 __releases(atalk_interfaces_lock
)
58 read_unlock_bh(&atalk_interfaces_lock
);
61 static int atalk_seq_interface_show(struct seq_file
*seq
, void *v
)
63 struct atalk_iface
*iface
;
65 if (v
== SEQ_START_TOKEN
) {
66 seq_puts(seq
, "Interface Address Networks "
72 seq_printf(seq
, "%-16s %04X:%02X %04X-%04X %d\n",
73 iface
->dev
->name
, ntohs(iface
->address
.s_net
),
74 iface
->address
.s_node
, ntohs(iface
->nets
.nr_firstnet
),
75 ntohs(iface
->nets
.nr_lastnet
), iface
->status
);
80 static __inline__
struct atalk_route
*atalk_get_route_idx(loff_t pos
)
82 struct atalk_route
*r
;
84 for (r
= atalk_routes
; pos
&& r
; r
= r
->next
)
90 static void *atalk_seq_route_start(struct seq_file
*seq
, loff_t
*pos
)
91 __acquires(atalk_routes_lock
)
95 read_lock_bh(&atalk_routes_lock
);
96 return l
? atalk_get_route_idx(--l
) : SEQ_START_TOKEN
;
99 static void *atalk_seq_route_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
101 struct atalk_route
*r
;
104 if (v
== SEQ_START_TOKEN
) {
116 static void atalk_seq_route_stop(struct seq_file
*seq
, void *v
)
117 __releases(atalk_routes_lock
)
119 read_unlock_bh(&atalk_routes_lock
);
122 static int atalk_seq_route_show(struct seq_file
*seq
, void *v
)
124 struct atalk_route
*rt
;
126 if (v
== SEQ_START_TOKEN
) {
127 seq_puts(seq
, "Target Router Flags Dev\n");
131 if (atrtr_default
.dev
) {
133 seq_printf(seq
, "Default %04X:%02X %-4d %s\n",
134 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
135 rt
->flags
, rt
->dev
->name
);
139 seq_printf(seq
, "%04X:%02X %04X:%02X %-4d %s\n",
140 ntohs(rt
->target
.s_net
), rt
->target
.s_node
,
141 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
142 rt
->flags
, rt
->dev
->name
);
147 static __inline__
struct sock
*atalk_get_socket_idx(loff_t pos
)
150 struct hlist_node
*node
;
152 sk_for_each(s
, node
, &atalk_sockets
)
160 static void *atalk_seq_socket_start(struct seq_file
*seq
, loff_t
*pos
)
161 __acquires(atalk_sockets_lock
)
165 read_lock_bh(&atalk_sockets_lock
);
166 return l
? atalk_get_socket_idx(--l
) : SEQ_START_TOKEN
;
169 static void *atalk_seq_socket_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
174 if (v
== SEQ_START_TOKEN
) {
175 i
= sk_head(&atalk_sockets
);
183 static void atalk_seq_socket_stop(struct seq_file
*seq
, void *v
)
184 __releases(atalk_sockets_lock
)
186 read_unlock_bh(&atalk_sockets_lock
);
189 static int atalk_seq_socket_show(struct seq_file
*seq
, void *v
)
192 struct atalk_sock
*at
;
194 if (v
== SEQ_START_TOKEN
) {
195 seq_printf(seq
, "Type Local_addr Remote_addr Tx_queue "
196 "Rx_queue St UID\n");
203 seq_printf(seq
, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X "
205 s
->sk_type
, ntohs(at
->src_net
), at
->src_node
, at
->src_port
,
206 ntohs(at
->dest_net
), at
->dest_node
, at
->dest_port
,
207 atomic_read(&s
->sk_wmem_alloc
),
208 atomic_read(&s
->sk_rmem_alloc
),
209 s
->sk_state
, SOCK_INODE(s
->sk_socket
)->i_uid
);
214 static const struct seq_operations atalk_seq_interface_ops
= {
215 .start
= atalk_seq_interface_start
,
216 .next
= atalk_seq_interface_next
,
217 .stop
= atalk_seq_interface_stop
,
218 .show
= atalk_seq_interface_show
,
221 static const struct seq_operations atalk_seq_route_ops
= {
222 .start
= atalk_seq_route_start
,
223 .next
= atalk_seq_route_next
,
224 .stop
= atalk_seq_route_stop
,
225 .show
= atalk_seq_route_show
,
228 static const struct seq_operations atalk_seq_socket_ops
= {
229 .start
= atalk_seq_socket_start
,
230 .next
= atalk_seq_socket_next
,
231 .stop
= atalk_seq_socket_stop
,
232 .show
= atalk_seq_socket_show
,
235 static int atalk_seq_interface_open(struct inode
*inode
, struct file
*file
)
237 return seq_open(file
, &atalk_seq_interface_ops
);
240 static int atalk_seq_route_open(struct inode
*inode
, struct file
*file
)
242 return seq_open(file
, &atalk_seq_route_ops
);
245 static int atalk_seq_socket_open(struct inode
*inode
, struct file
*file
)
247 return seq_open(file
, &atalk_seq_socket_ops
);
250 static const struct file_operations atalk_seq_interface_fops
= {
251 .owner
= THIS_MODULE
,
252 .open
= atalk_seq_interface_open
,
255 .release
= seq_release
,
258 static const struct file_operations atalk_seq_route_fops
= {
259 .owner
= THIS_MODULE
,
260 .open
= atalk_seq_route_open
,
263 .release
= seq_release
,
266 static const struct file_operations atalk_seq_socket_fops
= {
267 .owner
= THIS_MODULE
,
268 .open
= atalk_seq_socket_open
,
271 .release
= seq_release
,
274 static struct proc_dir_entry
*atalk_proc_dir
;
276 int __init
atalk_proc_init(void)
278 struct proc_dir_entry
*p
;
281 atalk_proc_dir
= proc_mkdir("atalk", init_net
.proc_net
);
284 atalk_proc_dir
->owner
= THIS_MODULE
;
286 p
= proc_create("interface", S_IRUGO
, atalk_proc_dir
,
287 &atalk_seq_interface_fops
);
291 p
= proc_create("route", S_IRUGO
, atalk_proc_dir
,
292 &atalk_seq_route_fops
);
296 p
= proc_create("socket", S_IRUGO
, atalk_proc_dir
,
297 &atalk_seq_socket_fops
);
301 p
= proc_create("arp", S_IRUGO
, atalk_proc_dir
, &atalk_seq_arp_fops
);
309 remove_proc_entry("socket", atalk_proc_dir
);
311 remove_proc_entry("route", atalk_proc_dir
);
313 remove_proc_entry("interface", atalk_proc_dir
);
315 remove_proc_entry("atalk", init_net
.proc_net
);
319 void __exit
atalk_proc_exit(void)
321 remove_proc_entry("interface", atalk_proc_dir
);
322 remove_proc_entry("route", atalk_proc_dir
);
323 remove_proc_entry("socket", atalk_proc_dir
);
324 remove_proc_entry("arp", atalk_proc_dir
);
325 remove_proc_entry("atalk", init_net
.proc_net
);