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>
15 #include <linux/atalk.h>
18 static __inline__
struct atalk_iface
*atalk_get_interface_idx(loff_t pos
)
20 struct atalk_iface
*i
;
22 for (i
= atalk_interfaces
; pos
&& i
; i
= i
->next
)
28 static void *atalk_seq_interface_start(struct seq_file
*seq
, loff_t
*pos
)
32 read_lock_bh(&atalk_interfaces_lock
);
33 return l
? atalk_get_interface_idx(--l
) : SEQ_START_TOKEN
;
36 static void *atalk_seq_interface_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
38 struct atalk_iface
*i
;
41 if (v
== SEQ_START_TOKEN
) {
53 static void atalk_seq_interface_stop(struct seq_file
*seq
, void *v
)
55 read_unlock_bh(&atalk_interfaces_lock
);
58 static int atalk_seq_interface_show(struct seq_file
*seq
, void *v
)
60 struct atalk_iface
*iface
;
62 if (v
== SEQ_START_TOKEN
) {
63 seq_puts(seq
, "Interface Address Networks "
69 seq_printf(seq
, "%-16s %04X:%02X %04X-%04X %d\n",
70 iface
->dev
->name
, ntohs(iface
->address
.s_net
),
71 iface
->address
.s_node
, ntohs(iface
->nets
.nr_firstnet
),
72 ntohs(iface
->nets
.nr_lastnet
), iface
->status
);
77 static __inline__
struct atalk_route
*atalk_get_route_idx(loff_t pos
)
79 struct atalk_route
*r
;
81 for (r
= atalk_routes
; pos
&& r
; r
= r
->next
)
87 static void *atalk_seq_route_start(struct seq_file
*seq
, loff_t
*pos
)
91 read_lock_bh(&atalk_routes_lock
);
92 return l
? atalk_get_route_idx(--l
) : SEQ_START_TOKEN
;
95 static void *atalk_seq_route_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
97 struct atalk_route
*r
;
100 if (v
== SEQ_START_TOKEN
) {
112 static void atalk_seq_route_stop(struct seq_file
*seq
, void *v
)
114 read_unlock_bh(&atalk_routes_lock
);
117 static int atalk_seq_route_show(struct seq_file
*seq
, void *v
)
119 struct atalk_route
*rt
;
121 if (v
== SEQ_START_TOKEN
) {
122 seq_puts(seq
, "Target Router Flags Dev\n");
126 if (atrtr_default
.dev
) {
128 seq_printf(seq
, "Default %04X:%02X %-4d %s\n",
129 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
130 rt
->flags
, rt
->dev
->name
);
134 seq_printf(seq
, "%04X:%02X %04X:%02X %-4d %s\n",
135 ntohs(rt
->target
.s_net
), rt
->target
.s_node
,
136 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
137 rt
->flags
, rt
->dev
->name
);
142 static __inline__
struct sock
*atalk_get_socket_idx(loff_t pos
)
145 struct hlist_node
*node
;
147 sk_for_each(s
, node
, &atalk_sockets
)
155 static void *atalk_seq_socket_start(struct seq_file
*seq
, loff_t
*pos
)
159 read_lock_bh(&atalk_sockets_lock
);
160 return l
? atalk_get_socket_idx(--l
) : SEQ_START_TOKEN
;
163 static void *atalk_seq_socket_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
168 if (v
== SEQ_START_TOKEN
) {
169 i
= sk_head(&atalk_sockets
);
177 static void atalk_seq_socket_stop(struct seq_file
*seq
, void *v
)
179 read_unlock_bh(&atalk_sockets_lock
);
182 static int atalk_seq_socket_show(struct seq_file
*seq
, void *v
)
185 struct atalk_sock
*at
;
187 if (v
== SEQ_START_TOKEN
) {
188 seq_printf(seq
, "Type Local_addr Remote_addr Tx_queue "
189 "Rx_queue St UID\n");
196 seq_printf(seq
, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X "
198 s
->sk_type
, ntohs(at
->src_net
), at
->src_node
, at
->src_port
,
199 ntohs(at
->dest_net
), at
->dest_node
, at
->dest_port
,
200 atomic_read(&s
->sk_wmem_alloc
),
201 atomic_read(&s
->sk_rmem_alloc
),
202 s
->sk_state
, SOCK_INODE(s
->sk_socket
)->i_uid
);
207 static struct seq_operations atalk_seq_interface_ops
= {
208 .start
= atalk_seq_interface_start
,
209 .next
= atalk_seq_interface_next
,
210 .stop
= atalk_seq_interface_stop
,
211 .show
= atalk_seq_interface_show
,
214 static struct seq_operations atalk_seq_route_ops
= {
215 .start
= atalk_seq_route_start
,
216 .next
= atalk_seq_route_next
,
217 .stop
= atalk_seq_route_stop
,
218 .show
= atalk_seq_route_show
,
221 static struct seq_operations atalk_seq_socket_ops
= {
222 .start
= atalk_seq_socket_start
,
223 .next
= atalk_seq_socket_next
,
224 .stop
= atalk_seq_socket_stop
,
225 .show
= atalk_seq_socket_show
,
228 static int atalk_seq_interface_open(struct inode
*inode
, struct file
*file
)
230 return seq_open(file
, &atalk_seq_interface_ops
);
233 static int atalk_seq_route_open(struct inode
*inode
, struct file
*file
)
235 return seq_open(file
, &atalk_seq_route_ops
);
238 static int atalk_seq_socket_open(struct inode
*inode
, struct file
*file
)
240 return seq_open(file
, &atalk_seq_socket_ops
);
243 static struct file_operations atalk_seq_interface_fops
= {
244 .owner
= THIS_MODULE
,
245 .open
= atalk_seq_interface_open
,
248 .release
= seq_release
,
251 static struct file_operations atalk_seq_route_fops
= {
252 .owner
= THIS_MODULE
,
253 .open
= atalk_seq_route_open
,
256 .release
= seq_release
,
259 static struct file_operations atalk_seq_socket_fops
= {
260 .owner
= THIS_MODULE
,
261 .open
= atalk_seq_socket_open
,
264 .release
= seq_release
,
267 static struct proc_dir_entry
*atalk_proc_dir
;
269 int __init
atalk_proc_init(void)
271 struct proc_dir_entry
*p
;
274 atalk_proc_dir
= proc_mkdir("atalk", proc_net
);
277 atalk_proc_dir
->owner
= THIS_MODULE
;
279 p
= create_proc_entry("interface", S_IRUGO
, atalk_proc_dir
);
282 p
->proc_fops
= &atalk_seq_interface_fops
;
284 p
= create_proc_entry("route", S_IRUGO
, atalk_proc_dir
);
287 p
->proc_fops
= &atalk_seq_route_fops
;
289 p
= create_proc_entry("socket", S_IRUGO
, atalk_proc_dir
);
292 p
->proc_fops
= &atalk_seq_socket_fops
;
294 p
= create_proc_entry("arp", S_IRUGO
, atalk_proc_dir
);
297 p
->proc_fops
= &atalk_seq_arp_fops
;
303 remove_proc_entry("socket", atalk_proc_dir
);
305 remove_proc_entry("route", atalk_proc_dir
);
307 remove_proc_entry("interface", atalk_proc_dir
);
309 remove_proc_entry("atalk", proc_net
);
313 void __exit
atalk_proc_exit(void)
315 remove_proc_entry("interface", atalk_proc_dir
);
316 remove_proc_entry("route", atalk_proc_dir
);
317 remove_proc_entry("socket", atalk_proc_dir
);
318 remove_proc_entry("arp", atalk_proc_dir
);
319 remove_proc_entry("atalk", proc_net
);