Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 33bc227e4e48ddadcf2eacb381c19df338f0a6c8 321 lines 7.2 kB view raw
1/* 2 * atalk_proc.c - proc support for Appletalk 3 * 4 * Copyright(c) Arnaldo Carvalho de Melo <acme@conectiva.com.br> 5 * 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. 9 */ 10 11#include <linux/config.h> 12#include <linux/init.h> 13#include <linux/proc_fs.h> 14#include <linux/seq_file.h> 15#include <net/sock.h> 16#include <linux/atalk.h> 17 18 19static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos) 20{ 21 struct atalk_iface *i; 22 23 for (i = atalk_interfaces; pos && i; i = i->next) 24 --pos; 25 26 return i; 27} 28 29static void *atalk_seq_interface_start(struct seq_file *seq, loff_t *pos) 30{ 31 loff_t l = *pos; 32 33 read_lock_bh(&atalk_interfaces_lock); 34 return l ? atalk_get_interface_idx(--l) : SEQ_START_TOKEN; 35} 36 37static void *atalk_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) 38{ 39 struct atalk_iface *i; 40 41 ++*pos; 42 if (v == SEQ_START_TOKEN) { 43 i = NULL; 44 if (atalk_interfaces) 45 i = atalk_interfaces; 46 goto out; 47 } 48 i = v; 49 i = i->next; 50out: 51 return i; 52} 53 54static void atalk_seq_interface_stop(struct seq_file *seq, void *v) 55{ 56 read_unlock_bh(&atalk_interfaces_lock); 57} 58 59static int atalk_seq_interface_show(struct seq_file *seq, void *v) 60{ 61 struct atalk_iface *iface; 62 63 if (v == SEQ_START_TOKEN) { 64 seq_puts(seq, "Interface Address Networks " 65 "Status\n"); 66 goto out; 67 } 68 69 iface = v; 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); 74out: 75 return 0; 76} 77 78static __inline__ struct atalk_route *atalk_get_route_idx(loff_t pos) 79{ 80 struct atalk_route *r; 81 82 for (r = atalk_routes; pos && r; r = r->next) 83 --pos; 84 85 return r; 86} 87 88static void *atalk_seq_route_start(struct seq_file *seq, loff_t *pos) 89{ 90 loff_t l = *pos; 91 92 read_lock_bh(&atalk_routes_lock); 93 return l ? atalk_get_route_idx(--l) : SEQ_START_TOKEN; 94} 95 96static void *atalk_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) 97{ 98 struct atalk_route *r; 99 100 ++*pos; 101 if (v == SEQ_START_TOKEN) { 102 r = NULL; 103 if (atalk_routes) 104 r = atalk_routes; 105 goto out; 106 } 107 r = v; 108 r = r->next; 109out: 110 return r; 111} 112 113static void atalk_seq_route_stop(struct seq_file *seq, void *v) 114{ 115 read_unlock_bh(&atalk_routes_lock); 116} 117 118static int atalk_seq_route_show(struct seq_file *seq, void *v) 119{ 120 struct atalk_route *rt; 121 122 if (v == SEQ_START_TOKEN) { 123 seq_puts(seq, "Target Router Flags Dev\n"); 124 goto out; 125 } 126 127 if (atrtr_default.dev) { 128 rt = &atrtr_default; 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); 132 } 133 134 rt = v; 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); 139out: 140 return 0; 141} 142 143static __inline__ struct sock *atalk_get_socket_idx(loff_t pos) 144{ 145 struct sock *s; 146 struct hlist_node *node; 147 148 sk_for_each(s, node, &atalk_sockets) 149 if (!pos--) 150 goto found; 151 s = NULL; 152found: 153 return s; 154} 155 156static void *atalk_seq_socket_start(struct seq_file *seq, loff_t *pos) 157{ 158 loff_t l = *pos; 159 160 read_lock_bh(&atalk_sockets_lock); 161 return l ? atalk_get_socket_idx(--l) : SEQ_START_TOKEN; 162} 163 164static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) 165{ 166 struct sock *i; 167 168 ++*pos; 169 if (v == SEQ_START_TOKEN) { 170 i = sk_head(&atalk_sockets); 171 goto out; 172 } 173 i = sk_next(v); 174out: 175 return i; 176} 177 178static void atalk_seq_socket_stop(struct seq_file *seq, void *v) 179{ 180 read_unlock_bh(&atalk_sockets_lock); 181} 182 183static int atalk_seq_socket_show(struct seq_file *seq, void *v) 184{ 185 struct sock *s; 186 struct atalk_sock *at; 187 188 if (v == SEQ_START_TOKEN) { 189 seq_printf(seq, "Type Local_addr Remote_addr Tx_queue " 190 "Rx_queue St UID\n"); 191 goto out; 192 } 193 194 s = v; 195 at = at_sk(s); 196 197 seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X " 198 "%02X %d\n", 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); 204out: 205 return 0; 206} 207 208static 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, 213}; 214 215static 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, 220}; 221 222static 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, 227}; 228 229static int atalk_seq_interface_open(struct inode *inode, struct file *file) 230{ 231 return seq_open(file, &atalk_seq_interface_ops); 232} 233 234static int atalk_seq_route_open(struct inode *inode, struct file *file) 235{ 236 return seq_open(file, &atalk_seq_route_ops); 237} 238 239static int atalk_seq_socket_open(struct inode *inode, struct file *file) 240{ 241 return seq_open(file, &atalk_seq_socket_ops); 242} 243 244static struct file_operations atalk_seq_interface_fops = { 245 .owner = THIS_MODULE, 246 .open = atalk_seq_interface_open, 247 .read = seq_read, 248 .llseek = seq_lseek, 249 .release = seq_release, 250}; 251 252static struct file_operations atalk_seq_route_fops = { 253 .owner = THIS_MODULE, 254 .open = atalk_seq_route_open, 255 .read = seq_read, 256 .llseek = seq_lseek, 257 .release = seq_release, 258}; 259 260static struct file_operations atalk_seq_socket_fops = { 261 .owner = THIS_MODULE, 262 .open = atalk_seq_socket_open, 263 .read = seq_read, 264 .llseek = seq_lseek, 265 .release = seq_release, 266}; 267 268static struct proc_dir_entry *atalk_proc_dir; 269 270int __init atalk_proc_init(void) 271{ 272 struct proc_dir_entry *p; 273 int rc = -ENOMEM; 274 275 atalk_proc_dir = proc_mkdir("atalk", proc_net); 276 if (!atalk_proc_dir) 277 goto out; 278 atalk_proc_dir->owner = THIS_MODULE; 279 280 p = create_proc_entry("interface", S_IRUGO, atalk_proc_dir); 281 if (!p) 282 goto out_interface; 283 p->proc_fops = &atalk_seq_interface_fops; 284 285 p = create_proc_entry("route", S_IRUGO, atalk_proc_dir); 286 if (!p) 287 goto out_route; 288 p->proc_fops = &atalk_seq_route_fops; 289 290 p = create_proc_entry("socket", S_IRUGO, atalk_proc_dir); 291 if (!p) 292 goto out_socket; 293 p->proc_fops = &atalk_seq_socket_fops; 294 295 p = create_proc_entry("arp", S_IRUGO, atalk_proc_dir); 296 if (!p) 297 goto out_arp; 298 p->proc_fops = &atalk_seq_arp_fops; 299 300 rc = 0; 301out: 302 return rc; 303out_arp: 304 remove_proc_entry("socket", atalk_proc_dir); 305out_socket: 306 remove_proc_entry("route", atalk_proc_dir); 307out_route: 308 remove_proc_entry("interface", atalk_proc_dir); 309out_interface: 310 remove_proc_entry("atalk", proc_net); 311 goto out; 312} 313 314void __exit atalk_proc_exit(void) 315{ 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); 321}