root/net/sctp/proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sctp_snmp_seq_show
  2. sctp_seq_dump_local_addrs
  3. sctp_seq_dump_remote_addrs
  4. sctp_eps_seq_start
  5. sctp_eps_seq_stop
  6. sctp_eps_seq_next
  7. sctp_eps_seq_show
  8. sctp_transport_seq_start
  9. sctp_transport_seq_stop
  10. sctp_transport_seq_next
  11. sctp_assocs_seq_show
  12. sctp_remaddr_seq_show
  13. sctp_proc_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* SCTP kernel implementation
   3  * Copyright (c) 2003 International Business Machines, Corp.
   4  *
   5  * This file is part of the SCTP kernel implementation
   6  *
   7  * Please send any bug reports or fixes you make to the
   8  * email address(es):
   9  *    lksctp developers <linux-sctp@vger.kernel.org>
  10  *
  11  * Written or modified by:
  12  *    Sridhar Samudrala <sri@us.ibm.com>
  13  */
  14 
  15 #include <linux/types.h>
  16 #include <linux/seq_file.h>
  17 #include <linux/init.h>
  18 #include <linux/export.h>
  19 #include <net/sctp/sctp.h>
  20 #include <net/ip.h> /* for snmp_fold_field */
  21 
  22 static const struct snmp_mib sctp_snmp_list[] = {
  23         SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB),
  24         SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS),
  25         SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS),
  26         SNMP_MIB_ITEM("SctpAborteds", SCTP_MIB_ABORTEDS),
  27         SNMP_MIB_ITEM("SctpShutdowns", SCTP_MIB_SHUTDOWNS),
  28         SNMP_MIB_ITEM("SctpOutOfBlues", SCTP_MIB_OUTOFBLUES),
  29         SNMP_MIB_ITEM("SctpChecksumErrors", SCTP_MIB_CHECKSUMERRORS),
  30         SNMP_MIB_ITEM("SctpOutCtrlChunks", SCTP_MIB_OUTCTRLCHUNKS),
  31         SNMP_MIB_ITEM("SctpOutOrderChunks", SCTP_MIB_OUTORDERCHUNKS),
  32         SNMP_MIB_ITEM("SctpOutUnorderChunks", SCTP_MIB_OUTUNORDERCHUNKS),
  33         SNMP_MIB_ITEM("SctpInCtrlChunks", SCTP_MIB_INCTRLCHUNKS),
  34         SNMP_MIB_ITEM("SctpInOrderChunks", SCTP_MIB_INORDERCHUNKS),
  35         SNMP_MIB_ITEM("SctpInUnorderChunks", SCTP_MIB_INUNORDERCHUNKS),
  36         SNMP_MIB_ITEM("SctpFragUsrMsgs", SCTP_MIB_FRAGUSRMSGS),
  37         SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS),
  38         SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS),
  39         SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS),
  40         SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS),
  41         SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS),
  42         SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS),
  43         SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS),
  44         SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS),
  45         SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS),
  46         SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS),
  47         SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS),
  48         SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS),
  49         SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS),
  50         SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS),
  51         SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ),
  52         SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG),
  53         SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS),
  54         SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS),
  55         SNMP_MIB_SENTINEL
  56 };
  57 
  58 /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
  59 static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
  60 {
  61         unsigned long buff[SCTP_MIB_MAX];
  62         struct net *net = seq->private;
  63         int i;
  64 
  65         memset(buff, 0, sizeof(unsigned long) * SCTP_MIB_MAX);
  66 
  67         snmp_get_cpu_field_batch(buff, sctp_snmp_list,
  68                                  net->sctp.sctp_statistics);
  69         for (i = 0; sctp_snmp_list[i].name; i++)
  70                 seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
  71                                                 buff[i]);
  72 
  73         return 0;
  74 }
  75 
  76 /* Dump local addresses of an association/endpoint. */
  77 static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
  78 {
  79         struct sctp_association *asoc;
  80         struct sctp_sockaddr_entry *laddr;
  81         struct sctp_transport *peer;
  82         union sctp_addr *addr, *primary = NULL;
  83         struct sctp_af *af;
  84 
  85         if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {
  86                 asoc = sctp_assoc(epb);
  87 
  88                 peer = asoc->peer.primary_path;
  89                 if (unlikely(peer == NULL)) {
  90                         WARN(1, "Association %p with NULL primary path!\n", asoc);
  91                         return;
  92                 }
  93 
  94                 primary = &peer->saddr;
  95         }
  96 
  97         rcu_read_lock();
  98         list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
  99                 if (!laddr->valid)
 100                         continue;
 101 
 102                 addr = &laddr->a;
 103                 af = sctp_get_af_specific(addr->sa.sa_family);
 104                 if (primary && af->cmp_addr(addr, primary)) {
 105                         seq_printf(seq, "*");
 106                 }
 107                 af->seq_dump_addr(seq, addr);
 108         }
 109         rcu_read_unlock();
 110 }
 111 
 112 /* Dump remote addresses of an association. */
 113 static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
 114 {
 115         struct sctp_transport *transport;
 116         union sctp_addr *addr, *primary;
 117         struct sctp_af *af;
 118 
 119         primary = &assoc->peer.primary_addr;
 120         list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
 121                         transports) {
 122                 addr = &transport->ipaddr;
 123 
 124                 af = sctp_get_af_specific(addr->sa.sa_family);
 125                 if (af->cmp_addr(addr, primary)) {
 126                         seq_printf(seq, "*");
 127                 }
 128                 af->seq_dump_addr(seq, addr);
 129         }
 130 }
 131 
 132 static void *sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 133 {
 134         if (*pos >= sctp_ep_hashsize)
 135                 return NULL;
 136 
 137         if (*pos < 0)
 138                 *pos = 0;
 139 
 140         if (*pos == 0)
 141                 seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
 142 
 143         return (void *)pos;
 144 }
 145 
 146 static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
 147 {
 148 }
 149 
 150 
 151 static void *sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 152 {
 153         if (++*pos >= sctp_ep_hashsize)
 154                 return NULL;
 155 
 156         return pos;
 157 }
 158 
 159 
 160 /* Display sctp endpoints (/proc/net/sctp/eps). */
 161 static int sctp_eps_seq_show(struct seq_file *seq, void *v)
 162 {
 163         struct sctp_hashbucket *head;
 164         struct sctp_ep_common *epb;
 165         struct sctp_endpoint *ep;
 166         struct sock *sk;
 167         int    hash = *(loff_t *)v;
 168 
 169         if (hash >= sctp_ep_hashsize)
 170                 return -ENOMEM;
 171 
 172         head = &sctp_ep_hashtable[hash];
 173         read_lock_bh(&head->lock);
 174         sctp_for_each_hentry(epb, &head->chain) {
 175                 ep = sctp_ep(epb);
 176                 sk = epb->sk;
 177                 if (!net_eq(sock_net(sk), seq_file_net(seq)))
 178                         continue;
 179                 seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5lu ", ep, sk,
 180                            sctp_sk(sk)->type, sk->sk_state, hash,
 181                            epb->bind_addr.port,
 182                            from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
 183                            sock_i_ino(sk));
 184 
 185                 sctp_seq_dump_local_addrs(seq, epb);
 186                 seq_printf(seq, "\n");
 187         }
 188         read_unlock_bh(&head->lock);
 189 
 190         return 0;
 191 }
 192 
 193 static const struct seq_operations sctp_eps_ops = {
 194         .start = sctp_eps_seq_start,
 195         .next  = sctp_eps_seq_next,
 196         .stop  = sctp_eps_seq_stop,
 197         .show  = sctp_eps_seq_show,
 198 };
 199 
 200 struct sctp_ht_iter {
 201         struct seq_net_private p;
 202         struct rhashtable_iter hti;
 203 };
 204 
 205 static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos)
 206 {
 207         struct sctp_ht_iter *iter = seq->private;
 208 
 209         sctp_transport_walk_start(&iter->hti);
 210 
 211         return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos);
 212 }
 213 
 214 static void sctp_transport_seq_stop(struct seq_file *seq, void *v)
 215 {
 216         struct sctp_ht_iter *iter = seq->private;
 217 
 218         sctp_transport_walk_stop(&iter->hti);
 219 }
 220 
 221 static void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 222 {
 223         struct sctp_ht_iter *iter = seq->private;
 224 
 225         ++*pos;
 226 
 227         return sctp_transport_get_next(seq_file_net(seq), &iter->hti);
 228 }
 229 
 230 /* Display sctp associations (/proc/net/sctp/assocs). */
 231 static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
 232 {
 233         struct sctp_transport *transport;
 234         struct sctp_association *assoc;
 235         struct sctp_ep_common *epb;
 236         struct sock *sk;
 237 
 238         if (v == SEQ_START_TOKEN) {
 239                 seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT "
 240                                 "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
 241                                 "RPORT LADDRS <-> RADDRS "
 242                                 "HBINT INS OUTS MAXRT T1X T2X RTXC "
 243                                 "wmema wmemq sndbuf rcvbuf\n");
 244                 return 0;
 245         }
 246 
 247         transport = (struct sctp_transport *)v;
 248         assoc = transport->asoc;
 249         epb = &assoc->base;
 250         sk = epb->sk;
 251 
 252         seq_printf(seq,
 253                    "%8pK %8pK %-3d %-3d %-2d %-4d "
 254                    "%4d %8d %8d %7u %5lu %-5d %5d ",
 255                    assoc, sk, sctp_sk(sk)->type, sk->sk_state,
 256                    assoc->state, 0,
 257                    assoc->assoc_id,
 258                    assoc->sndbuf_used,
 259                    atomic_read(&assoc->rmem_alloc),
 260                    from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
 261                    sock_i_ino(sk),
 262                    epb->bind_addr.port,
 263                    assoc->peer.port);
 264         seq_printf(seq, " ");
 265         sctp_seq_dump_local_addrs(seq, epb);
 266         seq_printf(seq, "<-> ");
 267         sctp_seq_dump_remote_addrs(seq, assoc);
 268         seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d "
 269                    "%8d %8d %8d %8d",
 270                 assoc->hbinterval, assoc->stream.incnt,
 271                 assoc->stream.outcnt, assoc->max_retrans,
 272                 assoc->init_retries, assoc->shutdown_retries,
 273                 assoc->rtx_data_chunks,
 274                 refcount_read(&sk->sk_wmem_alloc),
 275                 sk->sk_wmem_queued,
 276                 sk->sk_sndbuf,
 277                 sk->sk_rcvbuf);
 278         seq_printf(seq, "\n");
 279 
 280         sctp_transport_put(transport);
 281 
 282         return 0;
 283 }
 284 
 285 static const struct seq_operations sctp_assoc_ops = {
 286         .start = sctp_transport_seq_start,
 287         .next  = sctp_transport_seq_next,
 288         .stop  = sctp_transport_seq_stop,
 289         .show  = sctp_assocs_seq_show,
 290 };
 291 
 292 static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
 293 {
 294         struct sctp_association *assoc;
 295         struct sctp_transport *transport, *tsp;
 296 
 297         if (v == SEQ_START_TOKEN) {
 298                 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
 299                                 "REM_ADDR_RTX START STATE\n");
 300                 return 0;
 301         }
 302 
 303         transport = (struct sctp_transport *)v;
 304         assoc = transport->asoc;
 305 
 306         list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
 307                                 transports) {
 308                 /*
 309                  * The remote address (ADDR)
 310                  */
 311                 tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
 312                 seq_printf(seq, " ");
 313                 /*
 314                  * The association ID (ASSOC_ID)
 315                  */
 316                 seq_printf(seq, "%d ", tsp->asoc->assoc_id);
 317 
 318                 /*
 319                  * If the Heartbeat is active (HB_ACT)
 320                  * Note: 1 = Active, 0 = Inactive
 321                  */
 322                 seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
 323 
 324                 /*
 325                  * Retransmit time out (RTO)
 326                  */
 327                 seq_printf(seq, "%lu ", tsp->rto);
 328 
 329                 /*
 330                  * Maximum path retransmit count (PATH_MAX_RTX)
 331                  */
 332                 seq_printf(seq, "%d ", tsp->pathmaxrxt);
 333 
 334                 /*
 335                  * remote address retransmit count (REM_ADDR_RTX)
 336                  * Note: We don't have a way to tally this at the moment
 337                  * so lets just leave it as zero for the moment
 338                  */
 339                 seq_puts(seq, "0 ");
 340 
 341                 /*
 342                  * remote address start time (START).  This is also not
 343                  * currently implemented, but we can record it with a
 344                  * jiffies marker in a subsequent patch
 345                  */
 346                 seq_puts(seq, "0 ");
 347 
 348                 /*
 349                  * The current state of this destination. I.e.
 350                  * SCTP_ACTIVE, SCTP_INACTIVE, ...
 351                  */
 352                 seq_printf(seq, "%d", tsp->state);
 353 
 354                 seq_printf(seq, "\n");
 355         }
 356 
 357         sctp_transport_put(transport);
 358 
 359         return 0;
 360 }
 361 
 362 static const struct seq_operations sctp_remaddr_ops = {
 363         .start = sctp_transport_seq_start,
 364         .next  = sctp_transport_seq_next,
 365         .stop  = sctp_transport_seq_stop,
 366         .show  = sctp_remaddr_seq_show,
 367 };
 368 
 369 /* Set up the proc fs entry for the SCTP protocol. */
 370 int __net_init sctp_proc_init(struct net *net)
 371 {
 372         net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
 373         if (!net->sctp.proc_net_sctp)
 374                 return -ENOMEM;
 375         if (!proc_create_net_single("snmp", 0444, net->sctp.proc_net_sctp,
 376                          sctp_snmp_seq_show, NULL))
 377                 goto cleanup;
 378         if (!proc_create_net("eps", 0444, net->sctp.proc_net_sctp,
 379                         &sctp_eps_ops, sizeof(struct seq_net_private)))
 380                 goto cleanup;
 381         if (!proc_create_net("assocs", 0444, net->sctp.proc_net_sctp,
 382                         &sctp_assoc_ops, sizeof(struct sctp_ht_iter)))
 383                 goto cleanup;
 384         if (!proc_create_net("remaddr", 0444, net->sctp.proc_net_sctp,
 385                         &sctp_remaddr_ops, sizeof(struct sctp_ht_iter)))
 386                 goto cleanup;
 387         return 0;
 388 
 389 cleanup:
 390         remove_proc_subtree("sctp", net->proc_net);
 391         net->sctp.proc_net_sctp = NULL;
 392         return -ENOMEM;
 393 }

/* [<][>][^][v][top][bottom][index][help] */