1 /* SCTP kernel implementation 2 * Copyright (c) 2003 International Business Machines, Corp. 3 * 4 * This file is part of the SCTP kernel implementation 5 * 6 * This SCTP implementation is free software; 7 * you can redistribute it and/or modify it under the terms of 8 * the GNU General Public License as published by 9 * the Free Software Foundation; either version 2, or (at your option) 10 * any later version. 11 * 12 * This SCTP implementation is distributed in the hope that it 13 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 14 * ************************ 15 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 * See the GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with GNU CC; see the file COPYING. If not, see 20 * <http://www.gnu.org/licenses/>. 21 * 22 * Please send any bug reports or fixes you make to the 23 * email address(es): 24 * lksctp developers <linux-sctp@vger.kernel.org> 25 * 26 * Written or modified by: 27 * Sridhar Samudrala <sri@us.ibm.com> 28 */ 29 30 #include <linux/types.h> 31 #include <linux/seq_file.h> 32 #include <linux/init.h> 33 #include <linux/export.h> 34 #include <net/sctp/sctp.h> 35 #include <net/ip.h> /* for snmp_fold_field */ 36 37 static const struct snmp_mib sctp_snmp_list[] = { 38 SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB), 39 SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS), 40 SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS), 41 SNMP_MIB_ITEM("SctpAborteds", SCTP_MIB_ABORTEDS), 42 SNMP_MIB_ITEM("SctpShutdowns", SCTP_MIB_SHUTDOWNS), 43 SNMP_MIB_ITEM("SctpOutOfBlues", SCTP_MIB_OUTOFBLUES), 44 SNMP_MIB_ITEM("SctpChecksumErrors", SCTP_MIB_CHECKSUMERRORS), 45 SNMP_MIB_ITEM("SctpOutCtrlChunks", SCTP_MIB_OUTCTRLCHUNKS), 46 SNMP_MIB_ITEM("SctpOutOrderChunks", SCTP_MIB_OUTORDERCHUNKS), 47 SNMP_MIB_ITEM("SctpOutUnorderChunks", SCTP_MIB_OUTUNORDERCHUNKS), 48 SNMP_MIB_ITEM("SctpInCtrlChunks", SCTP_MIB_INCTRLCHUNKS), 49 SNMP_MIB_ITEM("SctpInOrderChunks", SCTP_MIB_INORDERCHUNKS), 50 SNMP_MIB_ITEM("SctpInUnorderChunks", SCTP_MIB_INUNORDERCHUNKS), 51 SNMP_MIB_ITEM("SctpFragUsrMsgs", SCTP_MIB_FRAGUSRMSGS), 52 SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS), 53 SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS), 54 SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS), 55 SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS), 56 SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS), 57 SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS), 58 SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS), 59 SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS), 60 SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS), 61 SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS), 62 SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS), 63 SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS), 64 SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS), 65 SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS), 66 SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ), 67 SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG), 68 SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS), 69 SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS), 70 SNMP_MIB_SENTINEL 71 }; 72 73 /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */ 74 static int sctp_snmp_seq_show(struct seq_file *seq, void *v) 75 { 76 unsigned long buff[SCTP_MIB_MAX]; 77 struct net *net = seq->private; 78 int i; 79 80 memset(buff, 0, sizeof(unsigned long) * SCTP_MIB_MAX); 81 82 snmp_get_cpu_field_batch(buff, sctp_snmp_list, 83 net->sctp.sctp_statistics); 84 for (i = 0; sctp_snmp_list[i].name; i++) 85 seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, 86 buff[i]); 87 88 return 0; 89 } 90 91 /* Initialize the seq file operations for 'snmp' object. */ 92 static int sctp_snmp_seq_open(struct inode *inode, struct file *file) 93 { 94 return single_open_net(inode, file, sctp_snmp_seq_show); 95 } 96 97 static const struct file_operations sctp_snmp_seq_fops = { 98 .open = sctp_snmp_seq_open, 99 .read = seq_read, 100 .llseek = seq_lseek, 101 .release = single_release_net, 102 }; 103 104 /* Set up the proc fs entry for 'snmp' object. */ 105 int __net_init sctp_snmp_proc_init(struct net *net) 106 { 107 struct proc_dir_entry *p; 108 109 p = proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp, 110 &sctp_snmp_seq_fops); 111 if (!p) 112 return -ENOMEM; 113 114 return 0; 115 } 116 117 /* Cleanup the proc fs entry for 'snmp' object. */ 118 void sctp_snmp_proc_exit(struct net *net) 119 { 120 remove_proc_entry("snmp", net->sctp.proc_net_sctp); 121 } 122 123 /* Dump local addresses of an association/endpoint. */ 124 static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb) 125 { 126 struct sctp_association *asoc; 127 struct sctp_sockaddr_entry *laddr; 128 struct sctp_transport *peer; 129 union sctp_addr *addr, *primary = NULL; 130 struct sctp_af *af; 131 132 if (epb->type == SCTP_EP_TYPE_ASSOCIATION) { 133 asoc = sctp_assoc(epb); 134 135 peer = asoc->peer.primary_path; 136 if (unlikely(peer == NULL)) { 137 WARN(1, "Association %p with NULL primary path!\n", asoc); 138 return; 139 } 140 141 primary = &peer->saddr; 142 } 143 144 rcu_read_lock(); 145 list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) { 146 if (!laddr->valid) 147 continue; 148 149 addr = &laddr->a; 150 af = sctp_get_af_specific(addr->sa.sa_family); 151 if (primary && af->cmp_addr(addr, primary)) { 152 seq_printf(seq, "*"); 153 } 154 af->seq_dump_addr(seq, addr); 155 } 156 rcu_read_unlock(); 157 } 158 159 /* Dump remote addresses of an association. */ 160 static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc) 161 { 162 struct sctp_transport *transport; 163 union sctp_addr *addr, *primary; 164 struct sctp_af *af; 165 166 primary = &assoc->peer.primary_addr; 167 list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list, 168 transports) { 169 addr = &transport->ipaddr; 170 171 af = sctp_get_af_specific(addr->sa.sa_family); 172 if (af->cmp_addr(addr, primary)) { 173 seq_printf(seq, "*"); 174 } 175 af->seq_dump_addr(seq, addr); 176 } 177 } 178 179 static void *sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) 180 { 181 if (*pos >= sctp_ep_hashsize) 182 return NULL; 183 184 if (*pos < 0) 185 *pos = 0; 186 187 if (*pos == 0) 188 seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n"); 189 190 return (void *)pos; 191 } 192 193 static void sctp_eps_seq_stop(struct seq_file *seq, void *v) 194 { 195 } 196 197 198 static void *sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos) 199 { 200 if (++*pos >= sctp_ep_hashsize) 201 return NULL; 202 203 return pos; 204 } 205 206 207 /* Display sctp endpoints (/proc/net/sctp/eps). */ 208 static int sctp_eps_seq_show(struct seq_file *seq, void *v) 209 { 210 struct sctp_hashbucket *head; 211 struct sctp_ep_common *epb; 212 struct sctp_endpoint *ep; 213 struct sock *sk; 214 int hash = *(loff_t *)v; 215 216 if (hash >= sctp_ep_hashsize) 217 return -ENOMEM; 218 219 head = &sctp_ep_hashtable[hash]; 220 read_lock_bh(&head->lock); 221 sctp_for_each_hentry(epb, &head->chain) { 222 ep = sctp_ep(epb); 223 sk = epb->sk; 224 if (!net_eq(sock_net(sk), seq_file_net(seq))) 225 continue; 226 seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5lu ", ep, sk, 227 sctp_sk(sk)->type, sk->sk_state, hash, 228 epb->bind_addr.port, 229 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), 230 sock_i_ino(sk)); 231 232 sctp_seq_dump_local_addrs(seq, epb); 233 seq_printf(seq, "\n"); 234 } 235 read_unlock_bh(&head->lock); 236 237 return 0; 238 } 239 240 static const struct seq_operations sctp_eps_ops = { 241 .start = sctp_eps_seq_start, 242 .next = sctp_eps_seq_next, 243 .stop = sctp_eps_seq_stop, 244 .show = sctp_eps_seq_show, 245 }; 246 247 248 /* Initialize the seq file operations for 'eps' object. */ 249 static int sctp_eps_seq_open(struct inode *inode, struct file *file) 250 { 251 return seq_open_net(inode, file, &sctp_eps_ops, 252 sizeof(struct seq_net_private)); 253 } 254 255 static const struct file_operations sctp_eps_seq_fops = { 256 .open = sctp_eps_seq_open, 257 .read = seq_read, 258 .llseek = seq_lseek, 259 .release = seq_release_net, 260 }; 261 262 /* Set up the proc fs entry for 'eps' object. */ 263 int __net_init sctp_eps_proc_init(struct net *net) 264 { 265 struct proc_dir_entry *p; 266 267 p = proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp, 268 &sctp_eps_seq_fops); 269 if (!p) 270 return -ENOMEM; 271 272 return 0; 273 } 274 275 /* Cleanup the proc fs entry for 'eps' object. */ 276 void sctp_eps_proc_exit(struct net *net) 277 { 278 remove_proc_entry("eps", net->sctp.proc_net_sctp); 279 } 280 281 struct sctp_ht_iter { 282 struct seq_net_private p; 283 struct rhashtable_iter hti; 284 int start_fail; 285 }; 286 287 static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) 288 { 289 struct sctp_ht_iter *iter = seq->private; 290 291 sctp_transport_walk_start(&iter->hti); 292 293 iter->start_fail = 0; 294 return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); 295 } 296 297 static void sctp_transport_seq_stop(struct seq_file *seq, void *v) 298 { 299 struct sctp_ht_iter *iter = seq->private; 300 301 if (iter->start_fail) 302 return; 303 sctp_transport_walk_stop(&iter->hti); 304 } 305 306 static void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos) 307 { 308 struct sctp_ht_iter *iter = seq->private; 309 310 ++*pos; 311 312 return sctp_transport_get_next(seq_file_net(seq), &iter->hti); 313 } 314 315 /* Display sctp associations (/proc/net/sctp/assocs). */ 316 static int sctp_assocs_seq_show(struct seq_file *seq, void *v) 317 { 318 struct sctp_transport *transport; 319 struct sctp_association *assoc; 320 struct sctp_ep_common *epb; 321 struct sock *sk; 322 323 if (v == SEQ_START_TOKEN) { 324 seq_printf(seq, " ASSOC SOCK STY SST ST HBKT " 325 "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " 326 "RPORT LADDRS <-> RADDRS " 327 "HBINT INS OUTS MAXRT T1X T2X RTXC " 328 "wmema wmemq sndbuf rcvbuf\n"); 329 return 0; 330 } 331 332 transport = (struct sctp_transport *)v; 333 if (!sctp_transport_hold(transport)) 334 return 0; 335 assoc = transport->asoc; 336 epb = &assoc->base; 337 sk = epb->sk; 338 339 seq_printf(seq, 340 "%8pK %8pK %-3d %-3d %-2d %-4d " 341 "%4d %8d %8d %7u %5lu %-5d %5d ", 342 assoc, sk, sctp_sk(sk)->type, sk->sk_state, 343 assoc->state, 0, 344 assoc->assoc_id, 345 assoc->sndbuf_used, 346 atomic_read(&assoc->rmem_alloc), 347 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), 348 sock_i_ino(sk), 349 epb->bind_addr.port, 350 assoc->peer.port); 351 seq_printf(seq, " "); 352 sctp_seq_dump_local_addrs(seq, epb); 353 seq_printf(seq, "<-> "); 354 sctp_seq_dump_remote_addrs(seq, assoc); 355 seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d " 356 "%8d %8d %8d %8d", 357 assoc->hbinterval, assoc->stream.incnt, 358 assoc->stream.outcnt, assoc->max_retrans, 359 assoc->init_retries, assoc->shutdown_retries, 360 assoc->rtx_data_chunks, 361 refcount_read(&sk->sk_wmem_alloc), 362 sk->sk_wmem_queued, 363 sk->sk_sndbuf, 364 sk->sk_rcvbuf); 365 seq_printf(seq, "\n"); 366 367 sctp_transport_put(transport); 368 369 return 0; 370 } 371 372 static const struct seq_operations sctp_assoc_ops = { 373 .start = sctp_transport_seq_start, 374 .next = sctp_transport_seq_next, 375 .stop = sctp_transport_seq_stop, 376 .show = sctp_assocs_seq_show, 377 }; 378 379 /* Initialize the seq file operations for 'assocs' object. */ 380 static int sctp_assocs_seq_open(struct inode *inode, struct file *file) 381 { 382 return seq_open_net(inode, file, &sctp_assoc_ops, 383 sizeof(struct sctp_ht_iter)); 384 } 385 386 static const struct file_operations sctp_assocs_seq_fops = { 387 .open = sctp_assocs_seq_open, 388 .read = seq_read, 389 .llseek = seq_lseek, 390 .release = seq_release_net, 391 }; 392 393 /* Set up the proc fs entry for 'assocs' object. */ 394 int __net_init sctp_assocs_proc_init(struct net *net) 395 { 396 struct proc_dir_entry *p; 397 398 p = proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp, 399 &sctp_assocs_seq_fops); 400 if (!p) 401 return -ENOMEM; 402 403 return 0; 404 } 405 406 /* Cleanup the proc fs entry for 'assocs' object. */ 407 void sctp_assocs_proc_exit(struct net *net) 408 { 409 remove_proc_entry("assocs", net->sctp.proc_net_sctp); 410 } 411 412 static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) 413 { 414 struct sctp_association *assoc; 415 struct sctp_transport *transport, *tsp; 416 417 if (v == SEQ_START_TOKEN) { 418 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " 419 "REM_ADDR_RTX START STATE\n"); 420 return 0; 421 } 422 423 transport = (struct sctp_transport *)v; 424 if (!sctp_transport_hold(transport)) 425 return 0; 426 assoc = transport->asoc; 427 428 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, 429 transports) { 430 /* 431 * The remote address (ADDR) 432 */ 433 tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); 434 seq_printf(seq, " "); 435 /* 436 * The association ID (ASSOC_ID) 437 */ 438 seq_printf(seq, "%d ", tsp->asoc->assoc_id); 439 440 /* 441 * If the Heartbeat is active (HB_ACT) 442 * Note: 1 = Active, 0 = Inactive 443 */ 444 seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); 445 446 /* 447 * Retransmit time out (RTO) 448 */ 449 seq_printf(seq, "%lu ", tsp->rto); 450 451 /* 452 * Maximum path retransmit count (PATH_MAX_RTX) 453 */ 454 seq_printf(seq, "%d ", tsp->pathmaxrxt); 455 456 /* 457 * remote address retransmit count (REM_ADDR_RTX) 458 * Note: We don't have a way to tally this at the moment 459 * so lets just leave it as zero for the moment 460 */ 461 seq_puts(seq, "0 "); 462 463 /* 464 * remote address start time (START). This is also not 465 * currently implemented, but we can record it with a 466 * jiffies marker in a subsequent patch 467 */ 468 seq_puts(seq, "0 "); 469 470 /* 471 * The current state of this destination. I.e. 472 * SCTP_ACTIVE, SCTP_INACTIVE, ... 473 */ 474 seq_printf(seq, "%d", tsp->state); 475 476 seq_printf(seq, "\n"); 477 } 478 479 sctp_transport_put(transport); 480 481 return 0; 482 } 483 484 static const struct seq_operations sctp_remaddr_ops = { 485 .start = sctp_transport_seq_start, 486 .next = sctp_transport_seq_next, 487 .stop = sctp_transport_seq_stop, 488 .show = sctp_remaddr_seq_show, 489 }; 490 491 /* Cleanup the proc fs entry for 'remaddr' object. */ 492 void sctp_remaddr_proc_exit(struct net *net) 493 { 494 remove_proc_entry("remaddr", net->sctp.proc_net_sctp); 495 } 496 497 static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) 498 { 499 return seq_open_net(inode, file, &sctp_remaddr_ops, 500 sizeof(struct sctp_ht_iter)); 501 } 502 503 static const struct file_operations sctp_remaddr_seq_fops = { 504 .open = sctp_remaddr_seq_open, 505 .read = seq_read, 506 .llseek = seq_lseek, 507 .release = seq_release_net, 508 }; 509 510 int __net_init sctp_remaddr_proc_init(struct net *net) 511 { 512 struct proc_dir_entry *p; 513 514 p = proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp, 515 &sctp_remaddr_seq_fops); 516 if (!p) 517 return -ENOMEM; 518 return 0; 519 } 520