linux/net/ipx/ipx_proc.c
<<
>>
Prefs
   1/*
   2 *      IPX proc routines
   3 *
   4 *      Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002
   5 */
   6
   7#include <linux/init.h>
   8#ifdef CONFIG_PROC_FS
   9#include <linux/proc_fs.h>
  10#include <linux/spinlock.h>
  11#include <linux/seq_file.h>
  12#include <linux/export.h>
  13#include <net/net_namespace.h>
  14#include <net/tcp_states.h>
  15#include <net/ipx.h>
  16
  17static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
  18{
  19        spin_lock_bh(&ipx_interfaces_lock);
  20        return seq_list_start_head(&ipx_interfaces, *pos);
  21}
  22
  23static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
  24{
  25        return seq_list_next(v, &ipx_interfaces, pos);
  26}
  27
  28static void ipx_seq_interface_stop(struct seq_file *seq, void *v)
  29{
  30        spin_unlock_bh(&ipx_interfaces_lock);
  31}
  32
  33static int ipx_seq_interface_show(struct seq_file *seq, void *v)
  34{
  35        struct ipx_interface *i;
  36
  37        if (v == &ipx_interfaces) {
  38                seq_puts(seq, "Network    Node_Address   Primary  Device     "
  39                              "Frame_Type");
  40#ifdef IPX_REFCNT_DEBUG
  41                seq_puts(seq, "  refcnt");
  42#endif
  43                seq_puts(seq, "\n");
  44                goto out;
  45        }
  46
  47        i = list_entry(v, struct ipx_interface, node);
  48        seq_printf(seq, "%08lX   ", (unsigned long int)ntohl(i->if_netnum));
  49        seq_printf(seq, "%02X%02X%02X%02X%02X%02X   ",
  50                        i->if_node[0], i->if_node[1], i->if_node[2],
  51                        i->if_node[3], i->if_node[4], i->if_node[5]);
  52        seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No");
  53        seq_printf(seq, "%-11s", ipx_device_name(i));
  54        seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
  55#ifdef IPX_REFCNT_DEBUG
  56        seq_printf(seq, "%6d", atomic_read(&i->refcnt));
  57#endif
  58        seq_puts(seq, "\n");
  59out:
  60        return 0;
  61}
  62
  63static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos)
  64{
  65        read_lock_bh(&ipx_routes_lock);
  66        return seq_list_start_head(&ipx_routes, *pos);
  67}
  68
  69static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
  70{
  71        return seq_list_next(v, &ipx_routes, pos);
  72}
  73
  74static void ipx_seq_route_stop(struct seq_file *seq, void *v)
  75{
  76        read_unlock_bh(&ipx_routes_lock);
  77}
  78
  79static int ipx_seq_route_show(struct seq_file *seq, void *v)
  80{
  81        struct ipx_route *rt;
  82
  83        if (v == &ipx_routes) {
  84                seq_puts(seq, "Network    Router_Net   Router_Node\n");
  85                goto out;
  86        }
  87
  88        rt = list_entry(v, struct ipx_route, node);
  89
  90        seq_printf(seq, "%08lX   ", (unsigned long int)ntohl(rt->ir_net));
  91        if (rt->ir_routed)
  92                seq_printf(seq, "%08lX     %02X%02X%02X%02X%02X%02X\n",
  93                           (long unsigned int)ntohl(rt->ir_intrfc->if_netnum),
  94                           rt->ir_router_node[0], rt->ir_router_node[1],
  95                           rt->ir_router_node[2], rt->ir_router_node[3],
  96                           rt->ir_router_node[4], rt->ir_router_node[5]);
  97        else
  98                seq_puts(seq, "Directly     Connected\n");
  99out:
 100        return 0;
 101}
 102
 103static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
 104{
 105        struct sock *s = NULL;
 106        struct hlist_node *node;
 107        struct ipx_interface *i;
 108
 109        list_for_each_entry(i, &ipx_interfaces, node) {
 110                spin_lock_bh(&i->if_sklist_lock);
 111                sk_for_each(s, node, &i->if_sklist) {
 112                        if (!pos)
 113                                break;
 114                        --pos;
 115                }
 116                spin_unlock_bh(&i->if_sklist_lock);
 117                if (!pos) {
 118                        if (node)
 119                                goto found;
 120                        break;
 121                }
 122        }
 123        s = NULL;
 124found:
 125        return s;
 126}
 127
 128static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos)
 129{
 130        loff_t l = *pos;
 131
 132        spin_lock_bh(&ipx_interfaces_lock);
 133        return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN;
 134}
 135
 136static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
 137{
 138        struct sock* sk, *next;
 139        struct ipx_interface *i;
 140        struct ipx_sock *ipxs;
 141
 142        ++*pos;
 143        if (v == SEQ_START_TOKEN) {
 144                sk = NULL;
 145                i = ipx_interfaces_head();
 146                if (!i)
 147                        goto out;
 148                sk = sk_head(&i->if_sklist);
 149                if (sk)
 150                        spin_lock_bh(&i->if_sklist_lock);
 151                goto out;
 152        }
 153        sk = v;
 154        next = sk_next(sk);
 155        if (next) {
 156                sk = next;
 157                goto out;
 158        }
 159        ipxs = ipx_sk(sk);
 160        i = ipxs->intrfc;
 161        spin_unlock_bh(&i->if_sklist_lock);
 162        sk = NULL;
 163        for (;;) {
 164                if (i->node.next == &ipx_interfaces)
 165                        break;
 166                i = list_entry(i->node.next, struct ipx_interface, node);
 167                spin_lock_bh(&i->if_sklist_lock);
 168                if (!hlist_empty(&i->if_sklist)) {
 169                        sk = sk_head(&i->if_sklist);
 170                        break;
 171                }
 172                spin_unlock_bh(&i->if_sklist_lock);
 173        }
 174out:
 175        return sk;
 176}
 177
 178static int ipx_seq_socket_show(struct seq_file *seq, void *v)
 179{
 180        struct sock *s;
 181        struct ipx_sock *ipxs;
 182
 183        if (v == SEQ_START_TOKEN) {
 184#ifdef CONFIG_IPX_INTERN
 185                seq_puts(seq, "Local_Address               "
 186                              "Remote_Address              Tx_Queue  "
 187                              "Rx_Queue  State  Uid\n");
 188#else
 189                seq_puts(seq, "Local_Address  Remote_Address              "
 190                              "Tx_Queue  Rx_Queue  State  Uid\n");
 191#endif
 192                goto out;
 193        }
 194
 195        s = v;
 196        ipxs = ipx_sk(s);
 197#ifdef CONFIG_IPX_INTERN
 198        seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 199                   (unsigned long)ntohl(ipxs->intrfc->if_netnum),
 200                   ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
 201                   ipxs->node[4], ipxs->node[5], ntohs(ipxs->port));
 202#else
 203        seq_printf(seq, "%08lX:%04X  ", (unsigned long) ntohl(ipxs->intrfc->if_netnum),
 204                   ntohs(ipxs->port));
 205#endif  /* CONFIG_IPX_INTERN */
 206        if (s->sk_state != TCP_ESTABLISHED)
 207                seq_printf(seq, "%-28s", "Not_Connected");
 208        else {
 209                seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 210                           (unsigned long)ntohl(ipxs->dest_addr.net),
 211                           ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
 212                           ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
 213                           ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
 214                           ntohs(ipxs->dest_addr.sock));
 215        }
 216
 217        seq_printf(seq, "%08X  %08X  %02X     %03d\n",
 218                   sk_wmem_alloc_get(s),
 219                   sk_rmem_alloc_get(s),
 220                   s->sk_state,
 221                   from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
 222out:
 223        return 0;
 224}
 225
 226static const struct seq_operations ipx_seq_interface_ops = {
 227        .start  = ipx_seq_interface_start,
 228        .next   = ipx_seq_interface_next,
 229        .stop   = ipx_seq_interface_stop,
 230        .show   = ipx_seq_interface_show,
 231};
 232
 233static const struct seq_operations ipx_seq_route_ops = {
 234        .start  = ipx_seq_route_start,
 235        .next   = ipx_seq_route_next,
 236        .stop   = ipx_seq_route_stop,
 237        .show   = ipx_seq_route_show,
 238};
 239
 240static const struct seq_operations ipx_seq_socket_ops = {
 241        .start  = ipx_seq_socket_start,
 242        .next   = ipx_seq_socket_next,
 243        .stop   = ipx_seq_interface_stop,
 244        .show   = ipx_seq_socket_show,
 245};
 246
 247static int ipx_seq_route_open(struct inode *inode, struct file *file)
 248{
 249        return seq_open(file, &ipx_seq_route_ops);
 250}
 251
 252static int ipx_seq_interface_open(struct inode *inode, struct file *file)
 253{
 254        return seq_open(file, &ipx_seq_interface_ops);
 255}
 256
 257static int ipx_seq_socket_open(struct inode *inode, struct file *file)
 258{
 259        return seq_open(file, &ipx_seq_socket_ops);
 260}
 261
 262static const struct file_operations ipx_seq_interface_fops = {
 263        .owner          = THIS_MODULE,
 264        .open           = ipx_seq_interface_open,
 265        .read           = seq_read,
 266        .llseek         = seq_lseek,
 267        .release        = seq_release,
 268};
 269
 270static const struct file_operations ipx_seq_route_fops = {
 271        .owner          = THIS_MODULE,
 272        .open           = ipx_seq_route_open,
 273        .read           = seq_read,
 274        .llseek         = seq_lseek,
 275        .release        = seq_release,
 276};
 277
 278static const struct file_operations ipx_seq_socket_fops = {
 279        .owner          = THIS_MODULE,
 280        .open           = ipx_seq_socket_open,
 281        .read           = seq_read,
 282        .llseek         = seq_lseek,
 283        .release        = seq_release,
 284};
 285
 286static struct proc_dir_entry *ipx_proc_dir;
 287
 288int __init ipx_proc_init(void)
 289{
 290        struct proc_dir_entry *p;
 291        int rc = -ENOMEM;
 292
 293        ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
 294
 295        if (!ipx_proc_dir)
 296                goto out;
 297        p = proc_create("interface", S_IRUGO,
 298                        ipx_proc_dir, &ipx_seq_interface_fops);
 299        if (!p)
 300                goto out_interface;
 301
 302        p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops);
 303        if (!p)
 304                goto out_route;
 305
 306        p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops);
 307        if (!p)
 308                goto out_socket;
 309
 310        rc = 0;
 311out:
 312        return rc;
 313out_socket:
 314        remove_proc_entry("route", ipx_proc_dir);
 315out_route:
 316        remove_proc_entry("interface", ipx_proc_dir);
 317out_interface:
 318        remove_proc_entry("ipx", init_net.proc_net);
 319        goto out;
 320}
 321
 322void __exit ipx_proc_exit(void)
 323{
 324        remove_proc_entry("interface", ipx_proc_dir);
 325        remove_proc_entry("route", ipx_proc_dir);
 326        remove_proc_entry("socket", ipx_proc_dir);
 327        remove_proc_entry("ipx", init_net.proc_net);
 328}
 329
 330#else /* CONFIG_PROC_FS */
 331
 332int __init ipx_proc_init(void)
 333{
 334        return 0;
 335}
 336
 337void __exit ipx_proc_exit(void)
 338{
 339}
 340
 341#endif /* CONFIG_PROC_FS */
 342