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