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