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>
17 #include <linux/export.h>
20 static __inline__
struct atalk_iface
*atalk_get_interface_idx(loff_t pos
)
22 struct atalk_iface
*i
;
24 for (i
= atalk_interfaces
; pos
&& i
; i
= i
->next
)
30 static void *atalk_seq_interface_start(struct seq_file
*seq
, loff_t
*pos
)
31 __acquires(atalk_interfaces_lock
)
35 read_lock_bh(&atalk_interfaces_lock
);
36 return l
? atalk_get_interface_idx(--l
) : SEQ_START_TOKEN
;
39 static void *atalk_seq_interface_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
41 struct atalk_iface
*i
;
44 if (v
== SEQ_START_TOKEN
) {
56 static void atalk_seq_interface_stop(struct seq_file
*seq
, void *v
)
57 __releases(atalk_interfaces_lock
)
59 read_unlock_bh(&atalk_interfaces_lock
);
62 static int atalk_seq_interface_show(struct seq_file
*seq
, void *v
)
64 struct atalk_iface
*iface
;
66 if (v
== SEQ_START_TOKEN
) {
67 seq_puts(seq
, "Interface Address Networks "
73 seq_printf(seq
, "%-16s %04X:%02X %04X-%04X %d\n",
74 iface
->dev
->name
, ntohs(iface
->address
.s_net
),
75 iface
->address
.s_node
, ntohs(iface
->nets
.nr_firstnet
),
76 ntohs(iface
->nets
.nr_lastnet
), iface
->status
);
81 static __inline__
struct atalk_route
*atalk_get_route_idx(loff_t pos
)
83 struct atalk_route
*r
;
85 for (r
= atalk_routes
; pos
&& r
; r
= r
->next
)
91 static void *atalk_seq_route_start(struct seq_file
*seq
, loff_t
*pos
)
92 __acquires(atalk_routes_lock
)
96 read_lock_bh(&atalk_routes_lock
);
97 return l
? atalk_get_route_idx(--l
) : SEQ_START_TOKEN
;
100 static void *atalk_seq_route_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
102 struct atalk_route
*r
;
105 if (v
== SEQ_START_TOKEN
) {
117 static void atalk_seq_route_stop(struct seq_file
*seq
, void *v
)
118 __releases(atalk_routes_lock
)
120 read_unlock_bh(&atalk_routes_lock
);
123 static int atalk_seq_route_show(struct seq_file
*seq
, void *v
)
125 struct atalk_route
*rt
;
127 if (v
== SEQ_START_TOKEN
) {
128 seq_puts(seq
, "Target Router Flags Dev\n");
132 if (atrtr_default
.dev
) {
134 seq_printf(seq
, "Default %04X:%02X %-4d %s\n",
135 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
136 rt
->flags
, rt
->dev
->name
);
140 seq_printf(seq
, "%04X:%02X %04X:%02X %-4d %s\n",
141 ntohs(rt
->target
.s_net
), rt
->target
.s_node
,
142 ntohs(rt
->gateway
.s_net
), rt
->gateway
.s_node
,
143 rt
->flags
, rt
->dev
->name
);
148 static void *atalk_seq_socket_start(struct seq_file
*seq
, loff_t
*pos
)
149 __acquires(atalk_sockets_lock
)
151 read_lock_bh(&atalk_sockets_lock
);
152 return seq_hlist_start_head(&atalk_sockets
, *pos
);
155 static void *atalk_seq_socket_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
157 return seq_hlist_next(v
, &atalk_sockets
, pos
);
160 static void atalk_seq_socket_stop(struct seq_file
*seq
, void *v
)
161 __releases(atalk_sockets_lock
)
163 read_unlock_bh(&atalk_sockets_lock
);
166 static int atalk_seq_socket_show(struct seq_file
*seq
, void *v
)
169 struct atalk_sock
*at
;
171 if (v
== SEQ_START_TOKEN
) {
172 seq_printf(seq
, "Type Local_addr Remote_addr Tx_queue "
173 "Rx_queue St UID\n");
180 seq_printf(seq
, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X "
182 s
->sk_type
, ntohs(at
->src_net
), at
->src_node
, at
->src_port
,
183 ntohs(at
->dest_net
), at
->dest_node
, at
->dest_port
,
184 sk_wmem_alloc_get(s
),
185 sk_rmem_alloc_get(s
),
186 s
->sk_state
, SOCK_INODE(s
->sk_socket
)->i_uid
);
191 static const struct seq_operations atalk_seq_interface_ops
= {
192 .start
= atalk_seq_interface_start
,
193 .next
= atalk_seq_interface_next
,
194 .stop
= atalk_seq_interface_stop
,
195 .show
= atalk_seq_interface_show
,
198 static const struct seq_operations atalk_seq_route_ops
= {
199 .start
= atalk_seq_route_start
,
200 .next
= atalk_seq_route_next
,
201 .stop
= atalk_seq_route_stop
,
202 .show
= atalk_seq_route_show
,
205 static const struct seq_operations atalk_seq_socket_ops
= {
206 .start
= atalk_seq_socket_start
,
207 .next
= atalk_seq_socket_next
,
208 .stop
= atalk_seq_socket_stop
,
209 .show
= atalk_seq_socket_show
,
212 static int atalk_seq_interface_open(struct inode
*inode
, struct file
*file
)
214 return seq_open(file
, &atalk_seq_interface_ops
);
217 static int atalk_seq_route_open(struct inode
*inode
, struct file
*file
)
219 return seq_open(file
, &atalk_seq_route_ops
);
222 static int atalk_seq_socket_open(struct inode
*inode
, struct file
*file
)
224 return seq_open(file
, &atalk_seq_socket_ops
);
227 static const struct file_operations atalk_seq_interface_fops
= {
228 .owner
= THIS_MODULE
,
229 .open
= atalk_seq_interface_open
,
232 .release
= seq_release
,
235 static const struct file_operations atalk_seq_route_fops
= {
236 .owner
= THIS_MODULE
,
237 .open
= atalk_seq_route_open
,
240 .release
= seq_release
,
243 static const struct file_operations atalk_seq_socket_fops
= {
244 .owner
= THIS_MODULE
,
245 .open
= atalk_seq_socket_open
,
248 .release
= seq_release
,
251 static struct proc_dir_entry
*atalk_proc_dir
;
253 int __init
atalk_proc_init(void)
255 struct proc_dir_entry
*p
;
258 atalk_proc_dir
= proc_mkdir("atalk", init_net
.proc_net
);
262 p
= proc_create("interface", S_IRUGO
, atalk_proc_dir
,
263 &atalk_seq_interface_fops
);
267 p
= proc_create("route", S_IRUGO
, atalk_proc_dir
,
268 &atalk_seq_route_fops
);
272 p
= proc_create("socket", S_IRUGO
, atalk_proc_dir
,
273 &atalk_seq_socket_fops
);
277 p
= proc_create("arp", S_IRUGO
, atalk_proc_dir
, &atalk_seq_arp_fops
);
285 remove_proc_entry("socket", atalk_proc_dir
);
287 remove_proc_entry("route", atalk_proc_dir
);
289 remove_proc_entry("interface", atalk_proc_dir
);
291 remove_proc_entry("atalk", init_net
.proc_net
);
295 void __exit
atalk_proc_exit(void)
297 remove_proc_entry("interface", atalk_proc_dir
);
298 remove_proc_entry("route", atalk_proc_dir
);
299 remove_proc_entry("socket", atalk_proc_dir
);
300 remove_proc_entry("arp", atalk_proc_dir
);
301 remove_proc_entry("atalk", init_net
.proc_net
);