18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* SCTP kernel implementation 38c2ecf20Sopenharmony_ci * Copyright (c) 2003 International Business Machines, Corp. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file is part of the SCTP kernel implementation 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Please send any bug reports or fixes you make to the 88c2ecf20Sopenharmony_ci * email address(es): 98c2ecf20Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Written or modified by: 128c2ecf20Sopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/types.h> 168c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/export.h> 198c2ecf20Sopenharmony_ci#include <net/sctp/sctp.h> 208c2ecf20Sopenharmony_ci#include <net/ip.h> /* for snmp_fold_field */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic const struct snmp_mib sctp_snmp_list[] = { 238c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB), 248c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS), 258c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS), 268c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpAborteds", SCTP_MIB_ABORTEDS), 278c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpShutdowns", SCTP_MIB_SHUTDOWNS), 288c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpOutOfBlues", SCTP_MIB_OUTOFBLUES), 298c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpChecksumErrors", SCTP_MIB_CHECKSUMERRORS), 308c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpOutCtrlChunks", SCTP_MIB_OUTCTRLCHUNKS), 318c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpOutOrderChunks", SCTP_MIB_OUTORDERCHUNKS), 328c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpOutUnorderChunks", SCTP_MIB_OUTUNORDERCHUNKS), 338c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInCtrlChunks", SCTP_MIB_INCTRLCHUNKS), 348c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInOrderChunks", SCTP_MIB_INORDERCHUNKS), 358c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInUnorderChunks", SCTP_MIB_INUNORDERCHUNKS), 368c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpFragUsrMsgs", SCTP_MIB_FRAGUSRMSGS), 378c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS), 388c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS), 398c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS), 408c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS), 418c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS), 428c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS), 438c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS), 448c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS), 458c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS), 468c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS), 478c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS), 488c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS), 498c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS), 508c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS), 518c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ), 528c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG), 538c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS), 548c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS), 558c2ecf20Sopenharmony_ci SNMP_MIB_SENTINEL 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */ 598c2ecf20Sopenharmony_cistatic int sctp_snmp_seq_show(struct seq_file *seq, void *v) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci unsigned long buff[SCTP_MIB_MAX]; 628c2ecf20Sopenharmony_ci struct net *net = seq->private; 638c2ecf20Sopenharmony_ci int i; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci memset(buff, 0, sizeof(unsigned long) * SCTP_MIB_MAX); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci snmp_get_cpu_field_batch(buff, sctp_snmp_list, 688c2ecf20Sopenharmony_ci net->sctp.sctp_statistics); 698c2ecf20Sopenharmony_ci for (i = 0; sctp_snmp_list[i].name; i++) 708c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, 718c2ecf20Sopenharmony_ci buff[i]); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return 0; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* Dump local addresses of an association/endpoint. */ 778c2ecf20Sopenharmony_cistatic void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci struct sctp_association *asoc; 808c2ecf20Sopenharmony_ci struct sctp_sockaddr_entry *laddr; 818c2ecf20Sopenharmony_ci struct sctp_transport *peer; 828c2ecf20Sopenharmony_ci union sctp_addr *addr, *primary = NULL; 838c2ecf20Sopenharmony_ci struct sctp_af *af; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (epb->type == SCTP_EP_TYPE_ASSOCIATION) { 868c2ecf20Sopenharmony_ci asoc = sctp_assoc(epb); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci peer = asoc->peer.primary_path; 898c2ecf20Sopenharmony_ci if (unlikely(peer == NULL)) { 908c2ecf20Sopenharmony_ci WARN(1, "Association %p with NULL primary path!\n", asoc); 918c2ecf20Sopenharmony_ci return; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci primary = &peer->saddr; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci rcu_read_lock(); 988c2ecf20Sopenharmony_ci list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) { 998c2ecf20Sopenharmony_ci if (!laddr->valid) 1008c2ecf20Sopenharmony_ci continue; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci addr = &laddr->a; 1038c2ecf20Sopenharmony_ci af = sctp_get_af_specific(addr->sa.sa_family); 1048c2ecf20Sopenharmony_ci if (primary && af->cmp_addr(addr, primary)) { 1058c2ecf20Sopenharmony_ci seq_printf(seq, "*"); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci af->seq_dump_addr(seq, addr); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci rcu_read_unlock(); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* Dump remote addresses of an association. */ 1138c2ecf20Sopenharmony_cistatic void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct sctp_transport *transport; 1168c2ecf20Sopenharmony_ci union sctp_addr *addr, *primary; 1178c2ecf20Sopenharmony_ci struct sctp_af *af; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci primary = &assoc->peer.primary_addr; 1208c2ecf20Sopenharmony_ci list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list, 1218c2ecf20Sopenharmony_ci transports) { 1228c2ecf20Sopenharmony_ci addr = &transport->ipaddr; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci af = sctp_get_af_specific(addr->sa.sa_family); 1258c2ecf20Sopenharmony_ci if (af->cmp_addr(addr, primary)) { 1268c2ecf20Sopenharmony_ci seq_printf(seq, "*"); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci af->seq_dump_addr(seq, addr); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic void *sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci if (*pos >= sctp_ep_hashsize) 1358c2ecf20Sopenharmony_ci return NULL; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (*pos < 0) 1388c2ecf20Sopenharmony_ci *pos = 0; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (*pos == 0) 1418c2ecf20Sopenharmony_ci seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n"); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return (void *)pos; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic void sctp_eps_seq_stop(struct seq_file *seq, void *v) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic void *sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci if (++*pos >= sctp_ep_hashsize) 1548c2ecf20Sopenharmony_ci return NULL; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return pos; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* Display sctp endpoints (/proc/net/sctp/eps). */ 1618c2ecf20Sopenharmony_cistatic int sctp_eps_seq_show(struct seq_file *seq, void *v) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct sctp_hashbucket *head; 1648c2ecf20Sopenharmony_ci struct sctp_ep_common *epb; 1658c2ecf20Sopenharmony_ci struct sctp_endpoint *ep; 1668c2ecf20Sopenharmony_ci struct sock *sk; 1678c2ecf20Sopenharmony_ci int hash = *(loff_t *)v; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (hash >= sctp_ep_hashsize) 1708c2ecf20Sopenharmony_ci return -ENOMEM; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci head = &sctp_ep_hashtable[hash]; 1738c2ecf20Sopenharmony_ci read_lock_bh(&head->lock); 1748c2ecf20Sopenharmony_ci sctp_for_each_hentry(epb, &head->chain) { 1758c2ecf20Sopenharmony_ci ep = sctp_ep(epb); 1768c2ecf20Sopenharmony_ci sk = epb->sk; 1778c2ecf20Sopenharmony_ci if (!net_eq(sock_net(sk), seq_file_net(seq))) 1788c2ecf20Sopenharmony_ci continue; 1798c2ecf20Sopenharmony_ci seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5lu ", ep, sk, 1808c2ecf20Sopenharmony_ci sctp_sk(sk)->type, sk->sk_state, hash, 1818c2ecf20Sopenharmony_ci epb->bind_addr.port, 1828c2ecf20Sopenharmony_ci from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), 1838c2ecf20Sopenharmony_ci sock_i_ino(sk)); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci sctp_seq_dump_local_addrs(seq, epb); 1868c2ecf20Sopenharmony_ci seq_printf(seq, "\n"); 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci read_unlock_bh(&head->lock); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic const struct seq_operations sctp_eps_ops = { 1948c2ecf20Sopenharmony_ci .start = sctp_eps_seq_start, 1958c2ecf20Sopenharmony_ci .next = sctp_eps_seq_next, 1968c2ecf20Sopenharmony_ci .stop = sctp_eps_seq_stop, 1978c2ecf20Sopenharmony_ci .show = sctp_eps_seq_show, 1988c2ecf20Sopenharmony_ci}; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistruct sctp_ht_iter { 2018c2ecf20Sopenharmony_ci struct seq_net_private p; 2028c2ecf20Sopenharmony_ci struct rhashtable_iter hti; 2038c2ecf20Sopenharmony_ci}; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct sctp_ht_iter *iter = seq->private; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci sctp_transport_walk_start(&iter->hti); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic void sctp_transport_seq_stop(struct seq_file *seq, void *v) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct sctp_ht_iter *iter = seq->private; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if (v && v != SEQ_START_TOKEN) { 2198c2ecf20Sopenharmony_ci struct sctp_transport *transport = v; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci sctp_transport_put(transport); 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci sctp_transport_walk_stop(&iter->hti); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct sctp_ht_iter *iter = seq->private; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (v && v != SEQ_START_TOKEN) { 2328c2ecf20Sopenharmony_ci struct sctp_transport *transport = v; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci sctp_transport_put(transport); 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci ++*pos; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return sctp_transport_get_next(seq_file_net(seq), &iter->hti); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci/* Display sctp associations (/proc/net/sctp/assocs). */ 2438c2ecf20Sopenharmony_cistatic int sctp_assocs_seq_show(struct seq_file *seq, void *v) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci struct sctp_transport *transport; 2468c2ecf20Sopenharmony_ci struct sctp_association *assoc; 2478c2ecf20Sopenharmony_ci struct sctp_ep_common *epb; 2488c2ecf20Sopenharmony_ci struct sock *sk; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (v == SEQ_START_TOKEN) { 2518c2ecf20Sopenharmony_ci seq_printf(seq, " ASSOC SOCK STY SST ST HBKT " 2528c2ecf20Sopenharmony_ci "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " 2538c2ecf20Sopenharmony_ci "RPORT LADDRS <-> RADDRS " 2548c2ecf20Sopenharmony_ci "HBINT INS OUTS MAXRT T1X T2X RTXC " 2558c2ecf20Sopenharmony_ci "wmema wmemq sndbuf rcvbuf\n"); 2568c2ecf20Sopenharmony_ci return 0; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci transport = (struct sctp_transport *)v; 2608c2ecf20Sopenharmony_ci assoc = transport->asoc; 2618c2ecf20Sopenharmony_ci epb = &assoc->base; 2628c2ecf20Sopenharmony_ci sk = epb->sk; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci seq_printf(seq, 2658c2ecf20Sopenharmony_ci "%8pK %8pK %-3d %-3d %-2d %-4d " 2668c2ecf20Sopenharmony_ci "%4d %8d %8d %7u %5lu %-5d %5d ", 2678c2ecf20Sopenharmony_ci assoc, sk, sctp_sk(sk)->type, sk->sk_state, 2688c2ecf20Sopenharmony_ci assoc->state, 0, 2698c2ecf20Sopenharmony_ci assoc->assoc_id, 2708c2ecf20Sopenharmony_ci assoc->sndbuf_used, 2718c2ecf20Sopenharmony_ci atomic_read(&assoc->rmem_alloc), 2728c2ecf20Sopenharmony_ci from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), 2738c2ecf20Sopenharmony_ci sock_i_ino(sk), 2748c2ecf20Sopenharmony_ci epb->bind_addr.port, 2758c2ecf20Sopenharmony_ci assoc->peer.port); 2768c2ecf20Sopenharmony_ci seq_printf(seq, " "); 2778c2ecf20Sopenharmony_ci sctp_seq_dump_local_addrs(seq, epb); 2788c2ecf20Sopenharmony_ci seq_printf(seq, "<-> "); 2798c2ecf20Sopenharmony_ci sctp_seq_dump_remote_addrs(seq, assoc); 2808c2ecf20Sopenharmony_ci seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d " 2818c2ecf20Sopenharmony_ci "%8d %8d %8d %8d", 2828c2ecf20Sopenharmony_ci assoc->hbinterval, assoc->stream.incnt, 2838c2ecf20Sopenharmony_ci assoc->stream.outcnt, assoc->max_retrans, 2848c2ecf20Sopenharmony_ci assoc->init_retries, assoc->shutdown_retries, 2858c2ecf20Sopenharmony_ci assoc->rtx_data_chunks, 2868c2ecf20Sopenharmony_ci refcount_read(&sk->sk_wmem_alloc), 2878c2ecf20Sopenharmony_ci READ_ONCE(sk->sk_wmem_queued), 2888c2ecf20Sopenharmony_ci sk->sk_sndbuf, 2898c2ecf20Sopenharmony_ci sk->sk_rcvbuf); 2908c2ecf20Sopenharmony_ci seq_printf(seq, "\n"); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci return 0; 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic const struct seq_operations sctp_assoc_ops = { 2968c2ecf20Sopenharmony_ci .start = sctp_transport_seq_start, 2978c2ecf20Sopenharmony_ci .next = sctp_transport_seq_next, 2988c2ecf20Sopenharmony_ci .stop = sctp_transport_seq_stop, 2998c2ecf20Sopenharmony_ci .show = sctp_assocs_seq_show, 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int sctp_remaddr_seq_show(struct seq_file *seq, void *v) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct sctp_association *assoc; 3058c2ecf20Sopenharmony_ci struct sctp_transport *transport, *tsp; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (v == SEQ_START_TOKEN) { 3088c2ecf20Sopenharmony_ci seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " 3098c2ecf20Sopenharmony_ci "REM_ADDR_RTX START STATE\n"); 3108c2ecf20Sopenharmony_ci return 0; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci transport = (struct sctp_transport *)v; 3148c2ecf20Sopenharmony_ci assoc = transport->asoc; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, 3178c2ecf20Sopenharmony_ci transports) { 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * The remote address (ADDR) 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_ci tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); 3228c2ecf20Sopenharmony_ci seq_printf(seq, " "); 3238c2ecf20Sopenharmony_ci /* 3248c2ecf20Sopenharmony_ci * The association ID (ASSOC_ID) 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_ci seq_printf(seq, "%d ", tsp->asoc->assoc_id); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* 3298c2ecf20Sopenharmony_ci * If the Heartbeat is active (HB_ACT) 3308c2ecf20Sopenharmony_ci * Note: 1 = Active, 0 = Inactive 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_ci seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci /* 3358c2ecf20Sopenharmony_ci * Retransmit time out (RTO) 3368c2ecf20Sopenharmony_ci */ 3378c2ecf20Sopenharmony_ci seq_printf(seq, "%lu ", tsp->rto); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* 3408c2ecf20Sopenharmony_ci * Maximum path retransmit count (PATH_MAX_RTX) 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_ci seq_printf(seq, "%d ", tsp->pathmaxrxt); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* 3458c2ecf20Sopenharmony_ci * remote address retransmit count (REM_ADDR_RTX) 3468c2ecf20Sopenharmony_ci * Note: We don't have a way to tally this at the moment 3478c2ecf20Sopenharmony_ci * so lets just leave it as zero for the moment 3488c2ecf20Sopenharmony_ci */ 3498c2ecf20Sopenharmony_ci seq_puts(seq, "0 "); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* 3528c2ecf20Sopenharmony_ci * remote address start time (START). This is also not 3538c2ecf20Sopenharmony_ci * currently implemented, but we can record it with a 3548c2ecf20Sopenharmony_ci * jiffies marker in a subsequent patch 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ci seq_puts(seq, "0 "); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* 3598c2ecf20Sopenharmony_ci * The current state of this destination. I.e. 3608c2ecf20Sopenharmony_ci * SCTP_ACTIVE, SCTP_INACTIVE, ... 3618c2ecf20Sopenharmony_ci */ 3628c2ecf20Sopenharmony_ci seq_printf(seq, "%d", tsp->state); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci seq_printf(seq, "\n"); 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci return 0; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic const struct seq_operations sctp_remaddr_ops = { 3718c2ecf20Sopenharmony_ci .start = sctp_transport_seq_start, 3728c2ecf20Sopenharmony_ci .next = sctp_transport_seq_next, 3738c2ecf20Sopenharmony_ci .stop = sctp_transport_seq_stop, 3748c2ecf20Sopenharmony_ci .show = sctp_remaddr_seq_show, 3758c2ecf20Sopenharmony_ci}; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci/* Set up the proc fs entry for the SCTP protocol. */ 3788c2ecf20Sopenharmony_ciint __net_init sctp_proc_init(struct net *net) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net); 3818c2ecf20Sopenharmony_ci if (!net->sctp.proc_net_sctp) 3828c2ecf20Sopenharmony_ci return -ENOMEM; 3838c2ecf20Sopenharmony_ci if (!proc_create_net_single("snmp", 0444, net->sctp.proc_net_sctp, 3848c2ecf20Sopenharmony_ci sctp_snmp_seq_show, NULL)) 3858c2ecf20Sopenharmony_ci goto cleanup; 3868c2ecf20Sopenharmony_ci if (!proc_create_net("eps", 0444, net->sctp.proc_net_sctp, 3878c2ecf20Sopenharmony_ci &sctp_eps_ops, sizeof(struct seq_net_private))) 3888c2ecf20Sopenharmony_ci goto cleanup; 3898c2ecf20Sopenharmony_ci if (!proc_create_net("assocs", 0444, net->sctp.proc_net_sctp, 3908c2ecf20Sopenharmony_ci &sctp_assoc_ops, sizeof(struct sctp_ht_iter))) 3918c2ecf20Sopenharmony_ci goto cleanup; 3928c2ecf20Sopenharmony_ci if (!proc_create_net("remaddr", 0444, net->sctp.proc_net_sctp, 3938c2ecf20Sopenharmony_ci &sctp_remaddr_ops, sizeof(struct sctp_ht_iter))) 3948c2ecf20Sopenharmony_ci goto cleanup; 3958c2ecf20Sopenharmony_ci return 0; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cicleanup: 3988c2ecf20Sopenharmony_ci remove_proc_subtree("sctp", net->proc_net); 3998c2ecf20Sopenharmony_ci net->sctp.proc_net_sctp = NULL; 4008c2ecf20Sopenharmony_ci return -ENOMEM; 4018c2ecf20Sopenharmony_ci} 402