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 void *atalk_seq_socket_start(struct seq_file
*seq
, loff_t
*pos
)
148 __acquires(atalk_sockets_lock
)
150 read_lock_bh(&atalk_sockets_lock
);
151 return seq_hlist_start_head(&atalk_sockets
, *pos
);
154 static void *atalk_seq_socket_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
156 return seq_hlist_next(v
, &atalk_sockets
, pos
);
159 static void atalk_seq_socket_stop(struct seq_file
*seq
, void *v
)
160 __releases(atalk_sockets_lock
)
162 read_unlock_bh(&atalk_sockets_lock
);
165 static int atalk_seq_socket_show(struct seq_file
*seq
, void *v
)
168 struct atalk_sock
*at
;
170 if (v
== SEQ_START_TOKEN
) {
171 seq_printf(seq
, "Type Local_addr Remote_addr Tx_queue "
172 "Rx_queue St UID\n");
179 seq_printf(seq
, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X "
181 s
->sk_type
, ntohs(at
->src_net
), at
->src_node
, at
->src_port
,
182 ntohs(at
->dest_net
), at
->dest_node
, at
->dest_port
,
183 sk_wmem_alloc_get(s
),
184 sk_rmem_alloc_get(s
),
185 s
->sk_state
, SOCK_INODE(s
->sk_socket
)->i_uid
);
190 static const struct seq_operations atalk_seq_interface_ops
= {
191 .start
= atalk_seq_interface_start
,
192 .next
= atalk_seq_interface_next
,
193 .stop
= atalk_seq_interface_stop
,
194 .show
= atalk_seq_interface_show
,
197 static const struct seq_operations atalk_seq_route_ops
= {
198 .start
= atalk_seq_route_start
,
199 .next
= atalk_seq_route_next
,
200 .stop
= atalk_seq_route_stop
,
201 .show
= atalk_seq_route_show
,
204 static const struct seq_operations atalk_seq_socket_ops
= {
205 .start
= atalk_seq_socket_start
,
206 .next
= atalk_seq_socket_next
,
207 .stop
= atalk_seq_socket_stop
,
208 .show
= atalk_seq_socket_show
,
211 static int atalk_seq_interface_open(struct inode
*inode
, struct file
*file
)
213 return seq_open(file
, &atalk_seq_interface_ops
);
216 static int atalk_seq_route_open(struct inode
*inode
, struct file
*file
)
218 return seq_open(file
, &atalk_seq_route_ops
);
221 static int atalk_seq_socket_open(struct inode
*inode
, struct file
*file
)
223 return seq_open(file
, &atalk_seq_socket_ops
);
226 static const struct file_operations atalk_seq_interface_fops
= {
227 .owner
= THIS_MODULE
,
228 .open
= atalk_seq_interface_open
,
231 .release
= seq_release
,
234 static const struct file_operations atalk_seq_route_fops
= {
235 .owner
= THIS_MODULE
,
236 .open
= atalk_seq_route_open
,
239 .release
= seq_release
,
242 static const struct file_operations atalk_seq_socket_fops
= {
243 .owner
= THIS_MODULE
,
244 .open
= atalk_seq_socket_open
,
247 .release
= seq_release
,
250 static struct proc_dir_entry
*atalk_proc_dir
;
252 int __init
atalk_proc_init(void)
254 struct proc_dir_entry
*p
;
257 atalk_proc_dir
= proc_mkdir("atalk", init_net
.proc_net
);
261 p
= proc_create("interface", S_IRUGO
, atalk_proc_dir
,
262 &atalk_seq_interface_fops
);
266 p
= proc_create("route", S_IRUGO
, atalk_proc_dir
,
267 &atalk_seq_route_fops
);
271 p
= proc_create("socket", S_IRUGO
, atalk_proc_dir
,
272 &atalk_seq_socket_fops
);
276 p
= proc_create("arp", S_IRUGO
, atalk_proc_dir
, &atalk_seq_arp_fops
);
284 remove_proc_entry("socket", atalk_proc_dir
);
286 remove_proc_entry("route", atalk_proc_dir
);
288 remove_proc_entry("interface", atalk_proc_dir
);
290 remove_proc_entry("atalk", init_net
.proc_net
);
294 void __exit
atalk_proc_exit(void)
296 remove_proc_entry("interface", atalk_proc_dir
);
297 remove_proc_entry("route", atalk_proc_dir
);
298 remove_proc_entry("socket", atalk_proc_dir
);
299 remove_proc_entry("arp", atalk_proc_dir
);
300 remove_proc_entry("atalk", init_net
.proc_net
);