1 /* SCTP kernel reference Implementation
2 * Copyright (c) 2003 International Business Machines, Corp.
4 * This file is part of the SCTP kernel reference Implementation
6 * The SCTP reference 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)
12 * The SCTP reference 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.
18 * You should have received a copy of the GNU General Public License
19 * along with GNU CC; see the file COPYING. If not, write to
20 * the Free Software Foundation, 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
23 * Please send any bug reports or fixes you make to the
25 * lksctp developers <lksctp-developers@lists.sourceforge.net>
27 * Or submit a bug report through the following website:
28 * http://www.sf.net/projects/lksctp
30 * Written or modified by:
31 * Sridhar Samudrala <sri@us.ibm.com>
33 * Any bugs reported given to us we will try to fix... any fixes shared will
34 * be incorporated into the next SCTP release.
37 #include <linux/types.h>
38 #include <linux/seq_file.h>
39 #include <linux/init.h>
40 #include <net/sctp/sctp.h>
42 static char *sctp_snmp_list
[] = {
43 #define SCTP_SNMP_ENTRY(x) #x
44 SCTP_SNMP_ENTRY(SctpCurrEstab
),
45 SCTP_SNMP_ENTRY(SctpActiveEstabs
),
46 SCTP_SNMP_ENTRY(SctpPassiveEstabs
),
47 SCTP_SNMP_ENTRY(SctpAborteds
),
48 SCTP_SNMP_ENTRY(SctpShutdowns
),
49 SCTP_SNMP_ENTRY(SctpOutOfBlues
),
50 SCTP_SNMP_ENTRY(SctpChecksumErrors
),
51 SCTP_SNMP_ENTRY(SctpOutCtrlChunks
),
52 SCTP_SNMP_ENTRY(SctpOutOrderChunks
),
53 SCTP_SNMP_ENTRY(SctpOutUnorderChunks
),
54 SCTP_SNMP_ENTRY(SctpInCtrlChunks
),
55 SCTP_SNMP_ENTRY(SctpInOrderChunks
),
56 SCTP_SNMP_ENTRY(SctpInUnorderChunks
),
57 SCTP_SNMP_ENTRY(SctpFragUsrMsgs
),
58 SCTP_SNMP_ENTRY(SctpReasmUsrMsgs
),
59 SCTP_SNMP_ENTRY(SctpOutSCTPPacks
),
60 SCTP_SNMP_ENTRY(SctpInSCTPPacks
),
61 #undef SCTP_SNMP_ENTRY
64 /* Return the current value of a particular entry in the mib by adding its
68 fold_field(void *mib
[], int nr
)
70 unsigned long res
= 0;
73 for (i
= 0; i
< NR_CPUS
; i
++) {
77 *((unsigned long *) (((void *) per_cpu_ptr(mib
[0], i
)) +
78 sizeof (unsigned long) * nr
));
80 *((unsigned long *) (((void *) per_cpu_ptr(mib
[1], i
)) +
81 sizeof (unsigned long) * nr
));
86 /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
87 static int sctp_snmp_seq_show(struct seq_file
*seq
, void *v
)
91 for (i
= 0; i
< sizeof(sctp_snmp_list
) / sizeof(char *); i
++)
92 seq_printf(seq
, "%-32s\t%ld\n", sctp_snmp_list
[i
],
93 fold_field((void **)sctp_statistics
, i
));
98 /* Initialize the seq file operations for 'snmp' object. */
99 static int sctp_snmp_seq_open(struct inode
*inode
, struct file
*file
)
101 return single_open(file
, sctp_snmp_seq_show
, NULL
);
104 static struct file_operations sctp_snmp_seq_fops
= {
105 .owner
= THIS_MODULE
,
106 .open
= sctp_snmp_seq_open
,
109 .release
= single_release
,
112 /* Set up the proc fs entry for 'snmp' object. */
113 int __init
sctp_snmp_proc_init(void)
115 struct proc_dir_entry
*p
;
117 p
= create_proc_entry("snmp", S_IRUGO
, proc_net_sctp
);
121 p
->proc_fops
= &sctp_snmp_seq_fops
;
126 /* Cleanup the proc fs entry for 'snmp' object. */
127 void sctp_snmp_proc_exit(void)
129 remove_proc_entry("snmp", proc_net_sctp
);
132 /* Dump local addresses of an association/endpoint. */
133 static void sctp_seq_dump_local_addrs(struct seq_file
*seq
, struct sctp_ep_common
*epb
)
135 struct list_head
*pos
;
136 struct sctp_sockaddr_entry
*laddr
;
137 union sctp_addr
*addr
;
140 list_for_each(pos
, &epb
->bind_addr
.address_list
) {
141 laddr
= list_entry(pos
, struct sctp_sockaddr_entry
, list
);
142 addr
= (union sctp_addr
*)&laddr
->a
;
143 af
= sctp_get_af_specific(addr
->sa
.sa_family
);
144 af
->seq_dump_addr(seq
, addr
);
148 /* Dump remote addresses of an association. */
149 static void sctp_seq_dump_remote_addrs(struct seq_file
*seq
, struct sctp_association
*assoc
)
151 struct list_head
*pos
;
152 struct sctp_transport
*transport
;
153 union sctp_addr
*addr
;
156 list_for_each(pos
, &assoc
->peer
.transport_addr_list
) {
157 transport
= list_entry(pos
, struct sctp_transport
, transports
);
158 addr
= (union sctp_addr
*)&transport
->ipaddr
;
159 af
= sctp_get_af_specific(addr
->sa
.sa_family
);
160 af
->seq_dump_addr(seq
, addr
);
164 /* Display sctp endpoints (/proc/net/sctp/eps). */
165 static int sctp_eps_seq_show(struct seq_file
*seq
, void *v
)
167 struct sctp_hashbucket
*head
;
168 struct sctp_ep_common
*epb
;
169 struct sctp_endpoint
*ep
;
173 seq_printf(seq
, " ENDPT SOCK STY SST HBKT LPORT LADDRS\n");
174 for (hash
= 0; hash
< sctp_ep_hashsize
; hash
++) {
175 head
= &sctp_ep_hashbucket
[hash
];
176 read_lock(&head
->lock
);
177 for (epb
= head
->chain
; epb
; epb
= epb
->next
) {
180 seq_printf(seq
, "%8p %8p %-3d %-3d %-4d %-5d ", ep
, sk
,
181 sctp_sk(sk
)->type
, sk
->sk_state
, hash
,
182 epb
->bind_addr
.port
);
183 sctp_seq_dump_local_addrs(seq
, epb
);
184 seq_printf(seq
, "\n");
186 read_unlock(&head
->lock
);
192 /* Initialize the seq file operations for 'eps' object. */
193 static int sctp_eps_seq_open(struct inode
*inode
, struct file
*file
)
195 return single_open(file
, sctp_eps_seq_show
, NULL
);
198 static struct file_operations sctp_eps_seq_fops
= {
199 .open
= sctp_eps_seq_open
,
202 .release
= single_release
,
205 /* Set up the proc fs entry for 'eps' object. */
206 int __init
sctp_eps_proc_init(void)
208 struct proc_dir_entry
*p
;
210 p
= create_proc_entry("eps", S_IRUGO
, proc_net_sctp
);
214 p
->proc_fops
= &sctp_eps_seq_fops
;
219 /* Cleanup the proc fs entry for 'eps' object. */
220 void sctp_eps_proc_exit(void)
222 remove_proc_entry("eps", proc_net_sctp
);
225 /* Display sctp associations (/proc/net/sctp/assocs). */
226 static int sctp_assocs_seq_show(struct seq_file
*seq
, void *v
)
228 struct sctp_hashbucket
*head
;
229 struct sctp_ep_common
*epb
;
230 struct sctp_association
*assoc
;
234 seq_printf(seq
, " ASSOC SOCK STY SST ST HBKT LPORT RPORT "
235 "LADDRS <-> RADDRS\n");
236 for (hash
= 0; hash
< sctp_assoc_hashsize
; hash
++) {
237 head
= &sctp_assoc_hashbucket
[hash
];
238 read_lock(&head
->lock
);
239 for (epb
= head
->chain
; epb
; epb
= epb
->next
) {
240 assoc
= sctp_assoc(epb
);
243 "%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ",
244 assoc
, sk
, sctp_sk(sk
)->type
, sk
->sk_state
,
245 assoc
->state
, hash
, epb
->bind_addr
.port
,
247 sctp_seq_dump_local_addrs(seq
, epb
);
248 seq_printf(seq
, "<-> ");
249 sctp_seq_dump_remote_addrs(seq
, assoc
);
250 seq_printf(seq
, "\n");
252 read_unlock(&head
->lock
);
258 /* Initialize the seq file operations for 'assocs' object. */
259 static int sctp_assocs_seq_open(struct inode
*inode
, struct file
*file
)
261 return single_open(file
, sctp_assocs_seq_show
, NULL
);
264 static struct file_operations sctp_assocs_seq_fops
= {
265 .open
= sctp_assocs_seq_open
,
268 .release
= single_release
,
271 /* Set up the proc fs entry for 'assocs' object. */
272 int __init
sctp_assocs_proc_init(void)
274 struct proc_dir_entry
*p
;
276 p
= create_proc_entry("assocs", S_IRUGO
, proc_net_sctp
);
280 p
->proc_fops
= &sctp_assocs_seq_fops
;
285 /* Cleanup the proc fs entry for 'assocs' object. */
286 void sctp_assocs_proc_exit(void)
288 remove_proc_entry("assocs", proc_net_sctp
);