162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* SCTP kernel implementation 362306a36Sopenharmony_ci * Copyright (c) 2003 International Business Machines, Corp. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file is part of the SCTP kernel implementation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the 862306a36Sopenharmony_ci * email address(es): 962306a36Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Written or modified by: 1262306a36Sopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/types.h> 1662306a36Sopenharmony_ci#include <linux/seq_file.h> 1762306a36Sopenharmony_ci#include <linux/init.h> 1862306a36Sopenharmony_ci#include <linux/export.h> 1962306a36Sopenharmony_ci#include <net/sctp/sctp.h> 2062306a36Sopenharmony_ci#include <net/ip.h> /* for snmp_fold_field */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic const struct snmp_mib sctp_snmp_list[] = { 2362306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB), 2462306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS), 2562306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS), 2662306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpAborteds", SCTP_MIB_ABORTEDS), 2762306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpShutdowns", SCTP_MIB_SHUTDOWNS), 2862306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpOutOfBlues", SCTP_MIB_OUTOFBLUES), 2962306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpChecksumErrors", SCTP_MIB_CHECKSUMERRORS), 3062306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpOutCtrlChunks", SCTP_MIB_OUTCTRLCHUNKS), 3162306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpOutOrderChunks", SCTP_MIB_OUTORDERCHUNKS), 3262306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpOutUnorderChunks", SCTP_MIB_OUTUNORDERCHUNKS), 3362306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInCtrlChunks", SCTP_MIB_INCTRLCHUNKS), 3462306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInOrderChunks", SCTP_MIB_INORDERCHUNKS), 3562306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInUnorderChunks", SCTP_MIB_INUNORDERCHUNKS), 3662306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpFragUsrMsgs", SCTP_MIB_FRAGUSRMSGS), 3762306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS), 3862306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS), 3962306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS), 4062306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS), 4162306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS), 4262306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS), 4362306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS), 4462306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS), 4562306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS), 4662306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS), 4762306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS), 4862306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS), 4962306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS), 5062306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS), 5162306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ), 5262306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG), 5362306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS), 5462306a36Sopenharmony_ci SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS), 5562306a36Sopenharmony_ci SNMP_MIB_SENTINEL 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */ 5962306a36Sopenharmony_cistatic int sctp_snmp_seq_show(struct seq_file *seq, void *v) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci unsigned long buff[SCTP_MIB_MAX]; 6262306a36Sopenharmony_ci struct net *net = seq->private; 6362306a36Sopenharmony_ci int i; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci memset(buff, 0, sizeof(unsigned long) * SCTP_MIB_MAX); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci snmp_get_cpu_field_batch(buff, sctp_snmp_list, 6862306a36Sopenharmony_ci net->sctp.sctp_statistics); 6962306a36Sopenharmony_ci for (i = 0; sctp_snmp_list[i].name; i++) 7062306a36Sopenharmony_ci seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, 7162306a36Sopenharmony_ci buff[i]); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci return 0; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* Dump local addresses of an association/endpoint. */ 7762306a36Sopenharmony_cistatic void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct sctp_association *asoc; 8062306a36Sopenharmony_ci struct sctp_sockaddr_entry *laddr; 8162306a36Sopenharmony_ci struct sctp_transport *peer; 8262306a36Sopenharmony_ci union sctp_addr *addr, *primary = NULL; 8362306a36Sopenharmony_ci struct sctp_af *af; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (epb->type == SCTP_EP_TYPE_ASSOCIATION) { 8662306a36Sopenharmony_ci asoc = sctp_assoc(epb); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci peer = asoc->peer.primary_path; 8962306a36Sopenharmony_ci if (unlikely(peer == NULL)) { 9062306a36Sopenharmony_ci WARN(1, "Association %p with NULL primary path!\n", asoc); 9162306a36Sopenharmony_ci return; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci primary = &peer->saddr; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci rcu_read_lock(); 9862306a36Sopenharmony_ci list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) { 9962306a36Sopenharmony_ci if (!laddr->valid) 10062306a36Sopenharmony_ci continue; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci addr = &laddr->a; 10362306a36Sopenharmony_ci af = sctp_get_af_specific(addr->sa.sa_family); 10462306a36Sopenharmony_ci if (primary && af->cmp_addr(addr, primary)) { 10562306a36Sopenharmony_ci seq_printf(seq, "*"); 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci af->seq_dump_addr(seq, addr); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci rcu_read_unlock(); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/* Dump remote addresses of an association. */ 11362306a36Sopenharmony_cistatic void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct sctp_transport *transport; 11662306a36Sopenharmony_ci union sctp_addr *addr, *primary; 11762306a36Sopenharmony_ci struct sctp_af *af; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci primary = &assoc->peer.primary_addr; 12062306a36Sopenharmony_ci list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list, 12162306a36Sopenharmony_ci transports) { 12262306a36Sopenharmony_ci addr = &transport->ipaddr; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci af = sctp_get_af_specific(addr->sa.sa_family); 12562306a36Sopenharmony_ci if (af->cmp_addr(addr, primary)) { 12662306a36Sopenharmony_ci seq_printf(seq, "*"); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci af->seq_dump_addr(seq, addr); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic void *sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci if (*pos >= sctp_ep_hashsize) 13562306a36Sopenharmony_ci return NULL; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (*pos < 0) 13862306a36Sopenharmony_ci *pos = 0; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (*pos == 0) 14162306a36Sopenharmony_ci seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n"); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return (void *)pos; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic void sctp_eps_seq_stop(struct seq_file *seq, void *v) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic void *sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci if (++*pos >= sctp_ep_hashsize) 15462306a36Sopenharmony_ci return NULL; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return pos; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* Display sctp endpoints (/proc/net/sctp/eps). */ 16162306a36Sopenharmony_cistatic int sctp_eps_seq_show(struct seq_file *seq, void *v) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct sctp_hashbucket *head; 16462306a36Sopenharmony_ci struct sctp_endpoint *ep; 16562306a36Sopenharmony_ci struct sock *sk; 16662306a36Sopenharmony_ci int hash = *(loff_t *)v; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (hash >= sctp_ep_hashsize) 16962306a36Sopenharmony_ci return -ENOMEM; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci head = &sctp_ep_hashtable[hash]; 17262306a36Sopenharmony_ci read_lock_bh(&head->lock); 17362306a36Sopenharmony_ci sctp_for_each_hentry(ep, &head->chain) { 17462306a36Sopenharmony_ci sk = ep->base.sk; 17562306a36Sopenharmony_ci if (!net_eq(sock_net(sk), seq_file_net(seq))) 17662306a36Sopenharmony_ci continue; 17762306a36Sopenharmony_ci seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5lu ", ep, sk, 17862306a36Sopenharmony_ci sctp_sk(sk)->type, sk->sk_state, hash, 17962306a36Sopenharmony_ci ep->base.bind_addr.port, 18062306a36Sopenharmony_ci from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), 18162306a36Sopenharmony_ci sock_i_ino(sk)); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci sctp_seq_dump_local_addrs(seq, &ep->base); 18462306a36Sopenharmony_ci seq_printf(seq, "\n"); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci read_unlock_bh(&head->lock); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return 0; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic const struct seq_operations sctp_eps_ops = { 19262306a36Sopenharmony_ci .start = sctp_eps_seq_start, 19362306a36Sopenharmony_ci .next = sctp_eps_seq_next, 19462306a36Sopenharmony_ci .stop = sctp_eps_seq_stop, 19562306a36Sopenharmony_ci .show = sctp_eps_seq_show, 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistruct sctp_ht_iter { 19962306a36Sopenharmony_ci struct seq_net_private p; 20062306a36Sopenharmony_ci struct rhashtable_iter hti; 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct sctp_ht_iter *iter = seq->private; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci sctp_transport_walk_start(&iter->hti); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic void sctp_transport_seq_stop(struct seq_file *seq, void *v) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct sctp_ht_iter *iter = seq->private; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (v && v != SEQ_START_TOKEN) { 21762306a36Sopenharmony_ci struct sctp_transport *transport = v; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci sctp_transport_put(transport); 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci sctp_transport_walk_stop(&iter->hti); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci struct sctp_ht_iter *iter = seq->private; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if (v && v != SEQ_START_TOKEN) { 23062306a36Sopenharmony_ci struct sctp_transport *transport = v; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci sctp_transport_put(transport); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci ++*pos; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci return sctp_transport_get_next(seq_file_net(seq), &iter->hti); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/* Display sctp associations (/proc/net/sctp/assocs). */ 24162306a36Sopenharmony_cistatic int sctp_assocs_seq_show(struct seq_file *seq, void *v) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci struct sctp_transport *transport; 24462306a36Sopenharmony_ci struct sctp_association *assoc; 24562306a36Sopenharmony_ci struct sctp_ep_common *epb; 24662306a36Sopenharmony_ci struct sock *sk; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (v == SEQ_START_TOKEN) { 24962306a36Sopenharmony_ci seq_printf(seq, " ASSOC SOCK STY SST ST HBKT " 25062306a36Sopenharmony_ci "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " 25162306a36Sopenharmony_ci "RPORT LADDRS <-> RADDRS " 25262306a36Sopenharmony_ci "HBINT INS OUTS MAXRT T1X T2X RTXC " 25362306a36Sopenharmony_ci "wmema wmemq sndbuf rcvbuf\n"); 25462306a36Sopenharmony_ci return 0; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci transport = (struct sctp_transport *)v; 25862306a36Sopenharmony_ci assoc = transport->asoc; 25962306a36Sopenharmony_ci epb = &assoc->base; 26062306a36Sopenharmony_ci sk = epb->sk; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci seq_printf(seq, 26362306a36Sopenharmony_ci "%8pK %8pK %-3d %-3d %-2d %-4d " 26462306a36Sopenharmony_ci "%4d %8d %8d %7u %5lu %-5d %5d ", 26562306a36Sopenharmony_ci assoc, sk, sctp_sk(sk)->type, sk->sk_state, 26662306a36Sopenharmony_ci assoc->state, 0, 26762306a36Sopenharmony_ci assoc->assoc_id, 26862306a36Sopenharmony_ci assoc->sndbuf_used, 26962306a36Sopenharmony_ci atomic_read(&assoc->rmem_alloc), 27062306a36Sopenharmony_ci from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), 27162306a36Sopenharmony_ci sock_i_ino(sk), 27262306a36Sopenharmony_ci epb->bind_addr.port, 27362306a36Sopenharmony_ci assoc->peer.port); 27462306a36Sopenharmony_ci seq_printf(seq, " "); 27562306a36Sopenharmony_ci sctp_seq_dump_local_addrs(seq, epb); 27662306a36Sopenharmony_ci seq_printf(seq, "<-> "); 27762306a36Sopenharmony_ci sctp_seq_dump_remote_addrs(seq, assoc); 27862306a36Sopenharmony_ci seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d " 27962306a36Sopenharmony_ci "%8d %8d %8d %8d", 28062306a36Sopenharmony_ci assoc->hbinterval, assoc->stream.incnt, 28162306a36Sopenharmony_ci assoc->stream.outcnt, assoc->max_retrans, 28262306a36Sopenharmony_ci assoc->init_retries, assoc->shutdown_retries, 28362306a36Sopenharmony_ci assoc->rtx_data_chunks, 28462306a36Sopenharmony_ci refcount_read(&sk->sk_wmem_alloc), 28562306a36Sopenharmony_ci READ_ONCE(sk->sk_wmem_queued), 28662306a36Sopenharmony_ci sk->sk_sndbuf, 28762306a36Sopenharmony_ci sk->sk_rcvbuf); 28862306a36Sopenharmony_ci seq_printf(seq, "\n"); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic const struct seq_operations sctp_assoc_ops = { 29462306a36Sopenharmony_ci .start = sctp_transport_seq_start, 29562306a36Sopenharmony_ci .next = sctp_transport_seq_next, 29662306a36Sopenharmony_ci .stop = sctp_transport_seq_stop, 29762306a36Sopenharmony_ci .show = sctp_assocs_seq_show, 29862306a36Sopenharmony_ci}; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic int sctp_remaddr_seq_show(struct seq_file *seq, void *v) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct sctp_association *assoc; 30362306a36Sopenharmony_ci struct sctp_transport *transport, *tsp; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (v == SEQ_START_TOKEN) { 30662306a36Sopenharmony_ci seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " 30762306a36Sopenharmony_ci "REM_ADDR_RTX START STATE\n"); 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci transport = (struct sctp_transport *)v; 31262306a36Sopenharmony_ci assoc = transport->asoc; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, 31562306a36Sopenharmony_ci transports) { 31662306a36Sopenharmony_ci /* 31762306a36Sopenharmony_ci * The remote address (ADDR) 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); 32062306a36Sopenharmony_ci seq_printf(seq, " "); 32162306a36Sopenharmony_ci /* 32262306a36Sopenharmony_ci * The association ID (ASSOC_ID) 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ci seq_printf(seq, "%d ", tsp->asoc->assoc_id); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* 32762306a36Sopenharmony_ci * If the Heartbeat is active (HB_ACT) 32862306a36Sopenharmony_ci * Note: 1 = Active, 0 = Inactive 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* 33362306a36Sopenharmony_ci * Retransmit time out (RTO) 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci seq_printf(seq, "%lu ", tsp->rto); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* 33862306a36Sopenharmony_ci * Maximum path retransmit count (PATH_MAX_RTX) 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci seq_printf(seq, "%d ", tsp->pathmaxrxt); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* 34362306a36Sopenharmony_ci * remote address retransmit count (REM_ADDR_RTX) 34462306a36Sopenharmony_ci * Note: We don't have a way to tally this at the moment 34562306a36Sopenharmony_ci * so lets just leave it as zero for the moment 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_ci seq_puts(seq, "0 "); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* 35062306a36Sopenharmony_ci * remote address start time (START). This is also not 35162306a36Sopenharmony_ci * currently implemented, but we can record it with a 35262306a36Sopenharmony_ci * jiffies marker in a subsequent patch 35362306a36Sopenharmony_ci */ 35462306a36Sopenharmony_ci seq_puts(seq, "0 "); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * The current state of this destination. I.e. 35862306a36Sopenharmony_ci * SCTP_ACTIVE, SCTP_INACTIVE, ... 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci seq_printf(seq, "%d", tsp->state); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci seq_printf(seq, "\n"); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return 0; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic const struct seq_operations sctp_remaddr_ops = { 36962306a36Sopenharmony_ci .start = sctp_transport_seq_start, 37062306a36Sopenharmony_ci .next = sctp_transport_seq_next, 37162306a36Sopenharmony_ci .stop = sctp_transport_seq_stop, 37262306a36Sopenharmony_ci .show = sctp_remaddr_seq_show, 37362306a36Sopenharmony_ci}; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/* Set up the proc fs entry for the SCTP protocol. */ 37662306a36Sopenharmony_ciint __net_init sctp_proc_init(struct net *net) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net); 37962306a36Sopenharmony_ci if (!net->sctp.proc_net_sctp) 38062306a36Sopenharmony_ci return -ENOMEM; 38162306a36Sopenharmony_ci if (!proc_create_net_single("snmp", 0444, net->sctp.proc_net_sctp, 38262306a36Sopenharmony_ci sctp_snmp_seq_show, NULL)) 38362306a36Sopenharmony_ci goto cleanup; 38462306a36Sopenharmony_ci if (!proc_create_net("eps", 0444, net->sctp.proc_net_sctp, 38562306a36Sopenharmony_ci &sctp_eps_ops, sizeof(struct seq_net_private))) 38662306a36Sopenharmony_ci goto cleanup; 38762306a36Sopenharmony_ci if (!proc_create_net("assocs", 0444, net->sctp.proc_net_sctp, 38862306a36Sopenharmony_ci &sctp_assoc_ops, sizeof(struct sctp_ht_iter))) 38962306a36Sopenharmony_ci goto cleanup; 39062306a36Sopenharmony_ci if (!proc_create_net("remaddr", 0444, net->sctp.proc_net_sctp, 39162306a36Sopenharmony_ci &sctp_remaddr_ops, sizeof(struct sctp_ht_iter))) 39262306a36Sopenharmony_ci goto cleanup; 39362306a36Sopenharmony_ci return 0; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cicleanup: 39662306a36Sopenharmony_ci remove_proc_subtree("sctp", net->proc_net); 39762306a36Sopenharmony_ci net->sctp.proc_net_sctp = NULL; 39862306a36Sopenharmony_ci return -ENOMEM; 39962306a36Sopenharmony_ci} 400