linux/net/rxrpc/proc.c
<<
>>
Prefs
   1/* /proc/net/ support for AF_RXRPC
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/module.h>
  13#include <net/sock.h>
  14#include <net/af_rxrpc.h>
  15#include "ar-internal.h"
  16
  17static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
  18        [RXRPC_CONN_UNUSED]                     = "Unused  ",
  19        [RXRPC_CONN_CLIENT]                     = "Client  ",
  20        [RXRPC_CONN_SERVICE_PREALLOC]           = "SvPrealc",
  21        [RXRPC_CONN_SERVICE_UNSECURED]          = "SvUnsec ",
  22        [RXRPC_CONN_SERVICE_CHALLENGING]        = "SvChall ",
  23        [RXRPC_CONN_SERVICE]                    = "SvSecure",
  24        [RXRPC_CONN_REMOTELY_ABORTED]           = "RmtAbort",
  25        [RXRPC_CONN_LOCALLY_ABORTED]            = "LocAbort",
  26};
  27
  28/*
  29 * generate a list of extant and dead calls in /proc/net/rxrpc_calls
  30 */
  31static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
  32        __acquires(rcu)
  33        __acquires(rxnet->call_lock)
  34{
  35        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  36
  37        rcu_read_lock();
  38        read_lock(&rxnet->call_lock);
  39        return seq_list_start_head(&rxnet->calls, *_pos);
  40}
  41
  42static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  43{
  44        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  45
  46        return seq_list_next(v, &rxnet->calls, pos);
  47}
  48
  49static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
  50        __releases(rxnet->call_lock)
  51        __releases(rcu)
  52{
  53        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  54
  55        read_unlock(&rxnet->call_lock);
  56        rcu_read_unlock();
  57}
  58
  59static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
  60{
  61        struct rxrpc_local *local;
  62        struct rxrpc_sock *rx;
  63        struct rxrpc_peer *peer;
  64        struct rxrpc_call *call;
  65        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  66        rxrpc_seq_t tx_hard_ack, rx_hard_ack;
  67        char lbuff[50], rbuff[50];
  68
  69        if (v == &rxnet->calls) {
  70                seq_puts(seq,
  71                         "Proto Local                                          "
  72                         " Remote                                         "
  73                         " SvID ConnID   CallID   End Use State    Abort   "
  74                         " UserID\n");
  75                return 0;
  76        }
  77
  78        call = list_entry(v, struct rxrpc_call, link);
  79
  80        rx = rcu_dereference(call->socket);
  81        if (rx) {
  82                local = READ_ONCE(rx->local);
  83                if (local)
  84                        sprintf(lbuff, "%pISpc", &local->srx.transport);
  85                else
  86                        strcpy(lbuff, "no_local");
  87        } else {
  88                strcpy(lbuff, "no_socket");
  89        }
  90
  91        peer = call->peer;
  92        if (peer)
  93                sprintf(rbuff, "%pISpc", &peer->srx.transport);
  94        else
  95                strcpy(rbuff, "no_connection");
  96
  97        tx_hard_ack = READ_ONCE(call->tx_hard_ack);
  98        rx_hard_ack = READ_ONCE(call->rx_hard_ack);
  99        seq_printf(seq,
 100                   "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
 101                   " %-8.8s %08x %lx %08x %02x %08x %02x\n",
 102                   lbuff,
 103                   rbuff,
 104                   call->service_id,
 105                   call->cid,
 106                   call->call_id,
 107                   rxrpc_is_service_call(call) ? "Svc" : "Clt",
 108                   atomic_read(&call->usage),
 109                   rxrpc_call_states[call->state],
 110                   call->abort_code,
 111                   call->user_call_ID,
 112                   tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
 113                   rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack);
 114
 115        return 0;
 116}
 117
 118static const struct seq_operations rxrpc_call_seq_ops = {
 119        .start  = rxrpc_call_seq_start,
 120        .next   = rxrpc_call_seq_next,
 121        .stop   = rxrpc_call_seq_stop,
 122        .show   = rxrpc_call_seq_show,
 123};
 124
 125static int rxrpc_call_seq_open(struct inode *inode, struct file *file)
 126{
 127        return seq_open_net(inode, file, &rxrpc_call_seq_ops,
 128                            sizeof(struct seq_net_private));
 129}
 130
 131const struct file_operations rxrpc_call_seq_fops = {
 132        .open           = rxrpc_call_seq_open,
 133        .read           = seq_read,
 134        .llseek         = seq_lseek,
 135        .release        = seq_release,
 136};
 137
 138/*
 139 * generate a list of extant virtual connections in /proc/net/rxrpc_conns
 140 */
 141static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
 142        __acquires(rxnet->conn_lock)
 143{
 144        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 145
 146        read_lock(&rxnet->conn_lock);
 147        return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
 148}
 149
 150static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
 151                                       loff_t *pos)
 152{
 153        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 154
 155        return seq_list_next(v, &rxnet->conn_proc_list, pos);
 156}
 157
 158static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
 159        __releases(rxnet->conn_lock)
 160{
 161        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 162
 163        read_unlock(&rxnet->conn_lock);
 164}
 165
 166static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
 167{
 168        struct rxrpc_connection *conn;
 169        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 170        char lbuff[50], rbuff[50];
 171
 172        if (v == &rxnet->conn_proc_list) {
 173                seq_puts(seq,
 174                         "Proto Local                                          "
 175                         " Remote                                         "
 176                         " SvID ConnID   End Use State    Key     "
 177                         " Serial   ISerial\n"
 178                         );
 179                return 0;
 180        }
 181
 182        conn = list_entry(v, struct rxrpc_connection, proc_link);
 183        if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
 184                strcpy(lbuff, "no_local");
 185                strcpy(rbuff, "no_connection");
 186                goto print;
 187        }
 188
 189        sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
 190
 191        sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
 192print:
 193        seq_printf(seq,
 194                   "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
 195                   " %s %08x %08x %08x\n",
 196                   lbuff,
 197                   rbuff,
 198                   conn->service_id,
 199                   conn->proto.cid,
 200                   rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
 201                   atomic_read(&conn->usage),
 202                   rxrpc_conn_states[conn->state],
 203                   key_serial(conn->params.key),
 204                   atomic_read(&conn->serial),
 205                   conn->hi_serial);
 206
 207        return 0;
 208}
 209
 210static const struct seq_operations rxrpc_connection_seq_ops = {
 211        .start  = rxrpc_connection_seq_start,
 212        .next   = rxrpc_connection_seq_next,
 213        .stop   = rxrpc_connection_seq_stop,
 214        .show   = rxrpc_connection_seq_show,
 215};
 216
 217
 218static int rxrpc_connection_seq_open(struct inode *inode, struct file *file)
 219{
 220        return seq_open_net(inode, file, &rxrpc_connection_seq_ops,
 221                            sizeof(struct seq_net_private));
 222}
 223
 224const struct file_operations rxrpc_connection_seq_fops = {
 225        .open           = rxrpc_connection_seq_open,
 226        .read           = seq_read,
 227        .llseek         = seq_lseek,
 228        .release        = seq_release,
 229};
 230