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 ipx_interface *i;
 107
 108        list_for_each_entry(i, &ipx_interfaces, node) {
 109                spin_lock_bh(&i->if_sklist_lock);
 110                sk_for_each(s, &i->if_sklist) {
 111                        if (!pos)
 112                                break;
 113                        --pos;
 114                }
 115                spin_unlock_bh(&i->if_sklist_lock);
 116                if (!pos) {
 117                        if (s)
 118                                goto found;
 119                        break;
 120                }
 121        }
 122        s = NULL;
 123found:
 124        return s;
 125}
 126
 127static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos)
 128{
 129        loff_t l = *pos;
 130
 131        spin_lock_bh(&ipx_interfaces_lock);
 132        return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN;
 133}
 134
 135static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
 136{
 137        struct sock* sk, *next;
 138        struct ipx_interface *i;
 139        struct ipx_sock *ipxs;
 140
 141        ++*pos;
 142        if (v == SEQ_START_TOKEN) {
 143                sk = NULL;
 144                i = ipx_interfaces_head();
 145                if (!i)
 146                        goto out;
 147                sk = sk_head(&i->if_sklist);
 148                if (sk)
 149                        spin_lock_bh(&i->if_sklist_lock);
 150                goto out;
 151        }
 152        sk = v;
 153        next = sk_next(sk);
 154        if (next) {
 155                sk = next;
 156                goto out;
 157        }
 158        ipxs = ipx_sk(sk);
 159        i = ipxs->intrfc;
 160        spin_unlock_bh(&i->if_sklist_lock);
 161        sk = NULL;
 162        for (;;) {
 163                if (i->node.next == &ipx_interfaces)
 164                        break;
 165                i = list_entry(i->node.next, struct ipx_interface, node);
 166                spin_lock_bh(&i->if_sklist_lock);
 167                if (!hlist_empty(&i->if_sklist)) {
 168                        sk = sk_head(&i->if_sklist);
 169                        break;
 170                }
 171                spin_unlock_bh(&i->if_sklist_lock);
 172        }
 173out:
 174        return sk;
 175}
 176
 177static int ipx_seq_socket_show(struct seq_file *seq, void *v)
 178{
 179        struct sock *s;
 180        struct ipx_sock *ipxs;
 181
 182        if (v == SEQ_START_TOKEN) {
 183#ifdef CONFIG_IPX_INTERN
 184                seq_puts(seq, "Local_Address               "
 185                              "Remote_Address              Tx_Queue  "
 186                              "Rx_Queue  State  Uid\n");
 187#else
 188                seq_puts(seq, "Local_Address  Remote_Address              "
 189                              "Tx_Queue  Rx_Queue  State  Uid\n");
 190#endif
 191                goto out;
 192        }
 193
 194        s = v;
 195        ipxs = ipx_sk(s);
 196#ifdef CONFIG_IPX_INTERN
 197        seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 198                   (unsigned long)ntohl(ipxs->intrfc->if_netnum),
 199                   ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
 200                   ipxs->node[4], ipxs->node[5], ntohs(ipxs->port));
 201#else
 202        seq_printf(seq, "%08lX:%04X  ", (unsigned long) ntohl(ipxs->intrfc->if_netnum),
 203                   ntohs(ipxs->port));
 204#endif  /* CONFIG_IPX_INTERN */
 205        if (s->sk_state != TCP_ESTABLISHED)
 206                seq_printf(seq, "%-28s", "Not_Connected");
 207        else {
 208                seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 209                           (unsigned long)ntohl(ipxs->dest_addr.net),
 210                           ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
 211                           ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
 212                           ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
 213                           ntohs(ipxs->dest_addr.sock));
 214        }
 215
 216        seq_printf(seq, "%08X  %08X  %02X     %03d\n",
 217                   sk_wmem_alloc_get(s),
 218                   sk_rmem_alloc_get(s),
 219                   s->sk_state,
 220                   from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
 221out:
 222        return 0;
 223}
 224
 225static const struct seq_operations ipx_seq_interface_ops = {
 226        .start  = ipx_seq_interface_start,
 227        .next   = ipx_seq_interface_next,
 228        .stop   = ipx_seq_interface_stop,
 229        .show   = ipx_seq_interface_show,
 230};
 231
 232static const struct seq_operations ipx_seq_route_ops = {
 233        .start  = ipx_seq_route_start,
 234        .next   = ipx_seq_route_next,
 235        .stop   = ipx_seq_route_stop,
 236        .show   = ipx_seq_route_show,
 237};
 238
 239static const struct seq_operations ipx_seq_socket_ops = {
 240        .start  = ipx_seq_socket_start,
 241        .next   = ipx_seq_socket_next,
 242        .stop   = ipx_seq_interface_stop,
 243        .show   = ipx_seq_socket_show,
 244};
 245
 246static int ipx_seq_route_open(struct inode *inode, struct file *file)
 247{
 248        return seq_open(file, &ipx_seq_route_ops);
 249}
 250
 251static int ipx_seq_interface_open(struct inode *inode, struct file *file)
 252{
 253        return seq_open(file, &ipx_seq_interface_ops);
 254}
 255
 256static int ipx_seq_socket_open(struct inode *inode, struct file *file)
 257{
 258        return seq_open(file, &ipx_seq_socket_ops);
 259}
 260
 261static const struct file_operations ipx_seq_interface_fops = {
 262        .owner          = THIS_MODULE,
 263        .open           = ipx_seq_interface_open,
 264        .read           = seq_read,
 265        .llseek         = seq_lseek,
 266        .release        = seq_release,
 267};
 268
 269static const struct file_operations ipx_seq_route_fops = {
 270        .owner          = THIS_MODULE,
 271        .open           = ipx_seq_route_open,
 272        .read           = seq_read,
 273        .llseek         = seq_lseek,
 274        .release        = seq_release,
 275};
 276
 277static const struct file_operations ipx_seq_socket_fops = {
 278        .owner          = THIS_MODULE,
 279        .open           = ipx_seq_socket_open,
 280        .read           = seq_read,
 281        .llseek         = seq_lseek,
 282        .release        = seq_release,
 283};
 284
 285static struct proc_dir_entry *ipx_proc_dir;
 286
 287int __init ipx_proc_init(void)
 288{
 289        struct proc_dir_entry *p;
 290        int rc = -ENOMEM;
 291
 292        ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
 293
 294        if (!ipx_proc_dir)
 295                goto out;
 296        p = proc_create("interface", S_IRUGO,
 297                        ipx_proc_dir, &ipx_seq_interface_fops);
 298        if (!p)
 299                goto out_interface;
 300
 301        p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops);
 302        if (!p)
 303                goto out_route;
 304
 305        p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops);
 306        if (!p)
 307                goto out_socket;
 308
 309        rc = 0;
 310out:
 311        return rc;
 312out_socket:
 313        remove_proc_entry("route", ipx_proc_dir);
 314out_route:
 315        remove_proc_entry("interface", ipx_proc_dir);
 316out_interface:
 317        remove_proc_entry("ipx", init_net.proc_net);
 318        goto out;
 319}
 320
 321void __exit ipx_proc_exit(void)
 322{
 323        remove_proc_entry("interface", ipx_proc_dir);
 324        remove_proc_entry("route", ipx_proc_dir);
 325        remove_proc_entry("socket", ipx_proc_dir);
 326        remove_proc_entry("ipx", init_net.proc_net);
 327}
 328
 329#else /* CONFIG_PROC_FS */
 330
 331int __init ipx_proc_init(void)
 332{
 333        return 0;
 334}
 335
 336void __exit ipx_proc_exit(void)
 337{
 338}
 339
 340#endif /* CONFIG_PROC_FS */
 341