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/config.h>
12 #include <linux/init.h>
13 #include <linux/proc_fs.h>
14 #include <linux/seq_file.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
)
33 read_lock_bh(&atalk_interfaces_lock
);
34 return l
? atalk_get_interface_idx(--l
) : SEQ_START_TOKEN
;
37 static void *atalk_seq_interface_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
39 struct atalk_iface
*i
;
42 if (v
== SEQ_START_TOKEN
) {
54 static void atalk_seq_interface_stop(struct seq_file
*seq
, void *v
)
56 read_unlock_bh(&atalk_interfaces_lock
);
59 static int atalk_seq_interface_show(struct seq_file
*seq
, void *v
)
61 struct atalk_iface
*iface
;
63 if (v
== SEQ_START_TOKEN
) {
64 seq_puts(seq
, "Interface Address Networks "
70 seq_printf(seq
, "%-16s %04X:%02X %04X-%04X %d\n",
71 iface
->dev
->name
, ntohs(iface
->address
.s_net
),
72 iface
->address
.s_node
, ntohs(iface
->nets
.nr_firstnet
),
73 ntohs(iface
->nets
.nr_lastnet
), iface
->status
);
78 static __inline__
struct atalk_route
*atalk_get_route_idx(loff_t pos
)
80 struct atalk_route
*r
;
82 for (r
= atalk_routes
; pos
&& r
; r
= r
->next
)
88 static void *atalk_seq_route_start(struct seq_file
*seq
, loff_t
*pos
)
92 read_lock_bh(&atalk_routes_lock
);
93 return l
? atalk_get_route_idx(--l
) : SEQ_START_TOKEN
;
96 static void *atalk_seq_route_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
98 struct atalk_route
*r
;
101 if (v
== SEQ_START_TOKEN
) {
113 static void atalk_seq_route_stop(struct seq_file
*seq
, void *v
)
115 read_unlock_bh(&atalk_routes_lock
);
118 static int atalk_seq_route_show(struct seq_file
*seq
, void *v
)
120 struct atalk_route
*rt
;
122 if (v
== SEQ_START_TOKEN
) {
123 seq_puts(seq
, "Target Router Flags Dev\n");
127 if (atrtr_default
.dev
) {
129 seq_printf(seq
, "Default %04X:%02X %-4d %s\n",
130 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
131 rt
->flags
, rt
->dev
->name
);
135 seq_printf(seq
, "%04X:%02X %04X:%02X %-4d %s\n",
136 ntohs(rt
->target
.s_net
), rt
->target
.s_node
,
137 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
138 rt
->flags
, rt
->dev
->name
);
143 static __inline__
struct sock
*atalk_get_socket_idx(loff_t pos
)
146 struct hlist_node
*node
;
148 sk_for_each(s
, node
, &atalk_sockets
)
156 static void *atalk_seq_socket_start(struct seq_file
*seq
, loff_t
*pos
)
160 read_lock_bh(&atalk_sockets_lock
);
161 return l
? atalk_get_socket_idx(--l
) : SEQ_START_TOKEN
;
164 static void *atalk_seq_socket_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
169 if (v
== SEQ_START_TOKEN
) {
170 i
= sk_head(&atalk_sockets
);
178 static void atalk_seq_socket_stop(struct seq_file
*seq
, void *v
)
180 read_unlock_bh(&atalk_sockets_lock
);
183 static int atalk_seq_socket_show(struct seq_file
*seq
, void *v
)
186 struct atalk_sock
*at
;
188 if (v
== SEQ_START_TOKEN
) {
189 seq_printf(seq
, "Type Local_addr Remote_addr Tx_queue "
190 "Rx_queue St UID\n");
197 seq_printf(seq
, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X "
199 s
->sk_type
, ntohs(at
->src_net
), at
->src_node
, at
->src_port
,
200 ntohs(at
->dest_net
), at
->dest_node
, at
->dest_port
,
201 atomic_read(&s
->sk_wmem_alloc
),
202 atomic_read(&s
->sk_rmem_alloc
),
203 s
->sk_state
, SOCK_INODE(s
->sk_socket
)->i_uid
);
208 static struct seq_operations atalk_seq_interface_ops
= {
209 .start
= atalk_seq_interface_start
,
210 .next
= atalk_seq_interface_next
,
211 .stop
= atalk_seq_interface_stop
,
212 .show
= atalk_seq_interface_show
,
215 static struct seq_operations atalk_seq_route_ops
= {
216 .start
= atalk_seq_route_start
,
217 .next
= atalk_seq_route_next
,
218 .stop
= atalk_seq_route_stop
,
219 .show
= atalk_seq_route_show
,
222 static struct seq_operations atalk_seq_socket_ops
= {
223 .start
= atalk_seq_socket_start
,
224 .next
= atalk_seq_socket_next
,
225 .stop
= atalk_seq_socket_stop
,
226 .show
= atalk_seq_socket_show
,
229 static int atalk_seq_interface_open(struct inode
*inode
, struct file
*file
)
231 return seq_open(file
, &atalk_seq_interface_ops
);
234 static int atalk_seq_route_open(struct inode
*inode
, struct file
*file
)
236 return seq_open(file
, &atalk_seq_route_ops
);
239 static int atalk_seq_socket_open(struct inode
*inode
, struct file
*file
)
241 return seq_open(file
, &atalk_seq_socket_ops
);
244 static struct file_operations atalk_seq_interface_fops
= {
245 .owner
= THIS_MODULE
,
246 .open
= atalk_seq_interface_open
,
249 .release
= seq_release
,
252 static struct file_operations atalk_seq_route_fops
= {
253 .owner
= THIS_MODULE
,
254 .open
= atalk_seq_route_open
,
257 .release
= seq_release
,
260 static struct file_operations atalk_seq_socket_fops
= {
261 .owner
= THIS_MODULE
,
262 .open
= atalk_seq_socket_open
,
265 .release
= seq_release
,
268 static struct proc_dir_entry
*atalk_proc_dir
;
270 int __init
atalk_proc_init(void)
272 struct proc_dir_entry
*p
;
275 atalk_proc_dir
= proc_mkdir("atalk", proc_net
);
278 atalk_proc_dir
->owner
= THIS_MODULE
;
280 p
= create_proc_entry("interface", S_IRUGO
, atalk_proc_dir
);
283 p
->proc_fops
= &atalk_seq_interface_fops
;
285 p
= create_proc_entry("route", S_IRUGO
, atalk_proc_dir
);
288 p
->proc_fops
= &atalk_seq_route_fops
;
290 p
= create_proc_entry("socket", S_IRUGO
, atalk_proc_dir
);
293 p
->proc_fops
= &atalk_seq_socket_fops
;
295 p
= create_proc_entry("arp", S_IRUGO
, atalk_proc_dir
);
298 p
->proc_fops
= &atalk_seq_arp_fops
;
304 remove_proc_entry("socket", atalk_proc_dir
);
306 remove_proc_entry("route", atalk_proc_dir
);
308 remove_proc_entry("interface", atalk_proc_dir
);
310 remove_proc_entry("atalk", proc_net
);
314 void __exit
atalk_proc_exit(void)
316 remove_proc_entry("interface", atalk_proc_dir
);
317 remove_proc_entry("route", atalk_proc_dir
);
318 remove_proc_entry("socket", atalk_proc_dir
);
319 remove_proc_entry("arp", atalk_proc_dir
);
320 remove_proc_entry("atalk", proc_net
);