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
 118const 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
 125/*
 126 * generate a list of extant virtual connections in /proc/net/rxrpc_conns
 127 */
 128static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
 129        __acquires(rxnet->conn_lock)
 130{
 131        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 132
 133        read_lock(&rxnet->conn_lock);
 134        return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
 135}
 136
 137static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
 138                                       loff_t *pos)
 139{
 140        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 141
 142        return seq_list_next(v, &rxnet->conn_proc_list, pos);
 143}
 144
 145static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
 146        __releases(rxnet->conn_lock)
 147{
 148        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 149
 150        read_unlock(&rxnet->conn_lock);
 151}
 152
 153static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
 154{
 155        struct rxrpc_connection *conn;
 156        struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 157        char lbuff[50], rbuff[50];
 158
 159        if (v == &rxnet->conn_proc_list) {
 160                seq_puts(seq,
 161                         "Proto Local                                          "
 162                         " Remote                                         "
 163                         " SvID ConnID   End Use State    Key     "
 164                         " Serial   ISerial\n"
 165                         );
 166                return 0;
 167        }
 168
 169        conn = list_entry(v, struct rxrpc_connection, proc_link);
 170        if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
 171                strcpy(lbuff, "no_local");
 172                strcpy(rbuff, "no_connection");
 173                goto print;
 174        }
 175
 176        sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
 177
 178        sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
 179print:
 180        seq_printf(seq,
 181                   "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
 182                   " %s %08x %08x %08x\n",
 183                   lbuff,
 184                   rbuff,
 185                   conn->service_id,
 186                   conn->proto.cid,
 187                   rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
 188                   atomic_read(&conn->usage),
 189                   rxrpc_conn_states[conn->state],
 190                   key_serial(conn->params.key),
 191                   atomic_read(&conn->serial),
 192                   conn->hi_serial);
 193
 194        return 0;
 195}
 196
 197const struct seq_operations rxrpc_connection_seq_ops = {
 198        .start  = rxrpc_connection_seq_start,
 199        .next   = rxrpc_connection_seq_next,
 200        .stop   = rxrpc_connection_seq_stop,
 201        .show   = rxrpc_connection_seq_show,
 202};
 203