0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/types.h>
0016 #include <linux/seq_file.h>
0017 #include <linux/init.h>
0018 #include <linux/export.h>
0019 #include <net/sctp/sctp.h>
0020 #include <net/ip.h> /* for snmp_fold_field */
0021
0022 static const struct snmp_mib sctp_snmp_list[] = {
0023 SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB),
0024 SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS),
0025 SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS),
0026 SNMP_MIB_ITEM("SctpAborteds", SCTP_MIB_ABORTEDS),
0027 SNMP_MIB_ITEM("SctpShutdowns", SCTP_MIB_SHUTDOWNS),
0028 SNMP_MIB_ITEM("SctpOutOfBlues", SCTP_MIB_OUTOFBLUES),
0029 SNMP_MIB_ITEM("SctpChecksumErrors", SCTP_MIB_CHECKSUMERRORS),
0030 SNMP_MIB_ITEM("SctpOutCtrlChunks", SCTP_MIB_OUTCTRLCHUNKS),
0031 SNMP_MIB_ITEM("SctpOutOrderChunks", SCTP_MIB_OUTORDERCHUNKS),
0032 SNMP_MIB_ITEM("SctpOutUnorderChunks", SCTP_MIB_OUTUNORDERCHUNKS),
0033 SNMP_MIB_ITEM("SctpInCtrlChunks", SCTP_MIB_INCTRLCHUNKS),
0034 SNMP_MIB_ITEM("SctpInOrderChunks", SCTP_MIB_INORDERCHUNKS),
0035 SNMP_MIB_ITEM("SctpInUnorderChunks", SCTP_MIB_INUNORDERCHUNKS),
0036 SNMP_MIB_ITEM("SctpFragUsrMsgs", SCTP_MIB_FRAGUSRMSGS),
0037 SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS),
0038 SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS),
0039 SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS),
0040 SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS),
0041 SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS),
0042 SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS),
0043 SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS),
0044 SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS),
0045 SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS),
0046 SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS),
0047 SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS),
0048 SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS),
0049 SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS),
0050 SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS),
0051 SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ),
0052 SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG),
0053 SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS),
0054 SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS),
0055 SNMP_MIB_SENTINEL
0056 };
0057
0058
0059 static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
0060 {
0061 unsigned long buff[SCTP_MIB_MAX];
0062 struct net *net = seq->private;
0063 int i;
0064
0065 memset(buff, 0, sizeof(unsigned long) * SCTP_MIB_MAX);
0066
0067 snmp_get_cpu_field_batch(buff, sctp_snmp_list,
0068 net->sctp.sctp_statistics);
0069 for (i = 0; sctp_snmp_list[i].name; i++)
0070 seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
0071 buff[i]);
0072
0073 return 0;
0074 }
0075
0076
0077 static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
0078 {
0079 struct sctp_association *asoc;
0080 struct sctp_sockaddr_entry *laddr;
0081 struct sctp_transport *peer;
0082 union sctp_addr *addr, *primary = NULL;
0083 struct sctp_af *af;
0084
0085 if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {
0086 asoc = sctp_assoc(epb);
0087
0088 peer = asoc->peer.primary_path;
0089 if (unlikely(peer == NULL)) {
0090 WARN(1, "Association %p with NULL primary path!\n", asoc);
0091 return;
0092 }
0093
0094 primary = &peer->saddr;
0095 }
0096
0097 rcu_read_lock();
0098 list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
0099 if (!laddr->valid)
0100 continue;
0101
0102 addr = &laddr->a;
0103 af = sctp_get_af_specific(addr->sa.sa_family);
0104 if (primary && af->cmp_addr(addr, primary)) {
0105 seq_printf(seq, "*");
0106 }
0107 af->seq_dump_addr(seq, addr);
0108 }
0109 rcu_read_unlock();
0110 }
0111
0112
0113 static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
0114 {
0115 struct sctp_transport *transport;
0116 union sctp_addr *addr, *primary;
0117 struct sctp_af *af;
0118
0119 primary = &assoc->peer.primary_addr;
0120 list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
0121 transports) {
0122 addr = &transport->ipaddr;
0123
0124 af = sctp_get_af_specific(addr->sa.sa_family);
0125 if (af->cmp_addr(addr, primary)) {
0126 seq_printf(seq, "*");
0127 }
0128 af->seq_dump_addr(seq, addr);
0129 }
0130 }
0131
0132 static void *sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
0133 {
0134 if (*pos >= sctp_ep_hashsize)
0135 return NULL;
0136
0137 if (*pos < 0)
0138 *pos = 0;
0139
0140 if (*pos == 0)
0141 seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n");
0142
0143 return (void *)pos;
0144 }
0145
0146 static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
0147 {
0148 }
0149
0150
0151 static void *sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
0152 {
0153 if (++*pos >= sctp_ep_hashsize)
0154 return NULL;
0155
0156 return pos;
0157 }
0158
0159
0160
0161 static int sctp_eps_seq_show(struct seq_file *seq, void *v)
0162 {
0163 struct sctp_hashbucket *head;
0164 struct sctp_endpoint *ep;
0165 struct sock *sk;
0166 int hash = *(loff_t *)v;
0167
0168 if (hash >= sctp_ep_hashsize)
0169 return -ENOMEM;
0170
0171 head = &sctp_ep_hashtable[hash];
0172 read_lock_bh(&head->lock);
0173 sctp_for_each_hentry(ep, &head->chain) {
0174 sk = ep->base.sk;
0175 if (!net_eq(sock_net(sk), seq_file_net(seq)))
0176 continue;
0177 seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5lu ", ep, sk,
0178 sctp_sk(sk)->type, sk->sk_state, hash,
0179 ep->base.bind_addr.port,
0180 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
0181 sock_i_ino(sk));
0182
0183 sctp_seq_dump_local_addrs(seq, &ep->base);
0184 seq_printf(seq, "\n");
0185 }
0186 read_unlock_bh(&head->lock);
0187
0188 return 0;
0189 }
0190
0191 static const struct seq_operations sctp_eps_ops = {
0192 .start = sctp_eps_seq_start,
0193 .next = sctp_eps_seq_next,
0194 .stop = sctp_eps_seq_stop,
0195 .show = sctp_eps_seq_show,
0196 };
0197
0198 struct sctp_ht_iter {
0199 struct seq_net_private p;
0200 struct rhashtable_iter hti;
0201 };
0202
0203 static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos)
0204 {
0205 struct sctp_ht_iter *iter = seq->private;
0206
0207 sctp_transport_walk_start(&iter->hti);
0208
0209 return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos);
0210 }
0211
0212 static void sctp_transport_seq_stop(struct seq_file *seq, void *v)
0213 {
0214 struct sctp_ht_iter *iter = seq->private;
0215
0216 if (v && v != SEQ_START_TOKEN) {
0217 struct sctp_transport *transport = v;
0218
0219 sctp_transport_put(transport);
0220 }
0221
0222 sctp_transport_walk_stop(&iter->hti);
0223 }
0224
0225 static void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos)
0226 {
0227 struct sctp_ht_iter *iter = seq->private;
0228
0229 if (v && v != SEQ_START_TOKEN) {
0230 struct sctp_transport *transport = v;
0231
0232 sctp_transport_put(transport);
0233 }
0234
0235 ++*pos;
0236
0237 return sctp_transport_get_next(seq_file_net(seq), &iter->hti);
0238 }
0239
0240
0241 static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
0242 {
0243 struct sctp_transport *transport;
0244 struct sctp_association *assoc;
0245 struct sctp_ep_common *epb;
0246 struct sock *sk;
0247
0248 if (v == SEQ_START_TOKEN) {
0249 seq_printf(seq, " ASSOC SOCK STY SST ST HBKT "
0250 "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
0251 "RPORT LADDRS <-> RADDRS "
0252 "HBINT INS OUTS MAXRT T1X T2X RTXC "
0253 "wmema wmemq sndbuf rcvbuf\n");
0254 return 0;
0255 }
0256
0257 transport = (struct sctp_transport *)v;
0258 assoc = transport->asoc;
0259 epb = &assoc->base;
0260 sk = epb->sk;
0261
0262 seq_printf(seq,
0263 "%8pK %8pK %-3d %-3d %-2d %-4d "
0264 "%4d %8d %8d %7u %5lu %-5d %5d ",
0265 assoc, sk, sctp_sk(sk)->type, sk->sk_state,
0266 assoc->state, 0,
0267 assoc->assoc_id,
0268 assoc->sndbuf_used,
0269 atomic_read(&assoc->rmem_alloc),
0270 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
0271 sock_i_ino(sk),
0272 epb->bind_addr.port,
0273 assoc->peer.port);
0274 seq_printf(seq, " ");
0275 sctp_seq_dump_local_addrs(seq, epb);
0276 seq_printf(seq, "<-> ");
0277 sctp_seq_dump_remote_addrs(seq, assoc);
0278 seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d "
0279 "%8d %8d %8d %8d",
0280 assoc->hbinterval, assoc->stream.incnt,
0281 assoc->stream.outcnt, assoc->max_retrans,
0282 assoc->init_retries, assoc->shutdown_retries,
0283 assoc->rtx_data_chunks,
0284 refcount_read(&sk->sk_wmem_alloc),
0285 sk->sk_wmem_queued,
0286 sk->sk_sndbuf,
0287 sk->sk_rcvbuf);
0288 seq_printf(seq, "\n");
0289
0290 return 0;
0291 }
0292
0293 static const struct seq_operations sctp_assoc_ops = {
0294 .start = sctp_transport_seq_start,
0295 .next = sctp_transport_seq_next,
0296 .stop = sctp_transport_seq_stop,
0297 .show = sctp_assocs_seq_show,
0298 };
0299
0300 static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
0301 {
0302 struct sctp_association *assoc;
0303 struct sctp_transport *transport, *tsp;
0304
0305 if (v == SEQ_START_TOKEN) {
0306 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
0307 "REM_ADDR_RTX START STATE\n");
0308 return 0;
0309 }
0310
0311 transport = (struct sctp_transport *)v;
0312 assoc = transport->asoc;
0313
0314 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
0315 transports) {
0316
0317
0318
0319 tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
0320 seq_printf(seq, " ");
0321
0322
0323
0324 seq_printf(seq, "%d ", tsp->asoc->assoc_id);
0325
0326
0327
0328
0329
0330 seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
0331
0332
0333
0334
0335 seq_printf(seq, "%lu ", tsp->rto);
0336
0337
0338
0339
0340 seq_printf(seq, "%d ", tsp->pathmaxrxt);
0341
0342
0343
0344
0345
0346
0347 seq_puts(seq, "0 ");
0348
0349
0350
0351
0352
0353
0354 seq_puts(seq, "0 ");
0355
0356
0357
0358
0359
0360 seq_printf(seq, "%d", tsp->state);
0361
0362 seq_printf(seq, "\n");
0363 }
0364
0365 return 0;
0366 }
0367
0368 static const struct seq_operations sctp_remaddr_ops = {
0369 .start = sctp_transport_seq_start,
0370 .next = sctp_transport_seq_next,
0371 .stop = sctp_transport_seq_stop,
0372 .show = sctp_remaddr_seq_show,
0373 };
0374
0375
0376 int __net_init sctp_proc_init(struct net *net)
0377 {
0378 net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
0379 if (!net->sctp.proc_net_sctp)
0380 return -ENOMEM;
0381 if (!proc_create_net_single("snmp", 0444, net->sctp.proc_net_sctp,
0382 sctp_snmp_seq_show, NULL))
0383 goto cleanup;
0384 if (!proc_create_net("eps", 0444, net->sctp.proc_net_sctp,
0385 &sctp_eps_ops, sizeof(struct seq_net_private)))
0386 goto cleanup;
0387 if (!proc_create_net("assocs", 0444, net->sctp.proc_net_sctp,
0388 &sctp_assoc_ops, sizeof(struct sctp_ht_iter)))
0389 goto cleanup;
0390 if (!proc_create_net("remaddr", 0444, net->sctp.proc_net_sctp,
0391 &sctp_remaddr_ops, sizeof(struct sctp_ht_iter)))
0392 goto cleanup;
0393 return 0;
0394
0395 cleanup:
0396 remove_proc_subtree("sctp", net->proc_net);
0397 net->sctp.proc_net_sctp = NULL;
0398 return -ENOMEM;
0399 }