xref: /kernel/linux/linux-6.6/net/sctp/proc.c (revision 62306a36)
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