Skip to content

Commit 4e811b1

Browse files
committed
Merge branch 'sctp-diag'
Xin Long says: ==================== sctp: support sctp_diag in kernel This patchset will add sctp_diag module to implement diag interface on sctp in kernel. For a listening sctp endpoint, we will just dump it's ep info. For a sctp connection, we will the assoc info and it's ep info. The ss dump will looks like: [iproute2]# ./misc/ss --sctp -n -l State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 172.16.254.254:8888 *:* LISTEN 0 5 127.0.0.1:1234 *:* LISTEN 0 5 127.0.0.1:1234 *:* - ESTAB 0 0 127.0.0.1%lo:1234 127.0.0.1:4321 LISTEN 0 128 172.16.254.254:8888 *:* - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.253.253:8888 - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.1.1:8888 - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.1.2:8888 - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.2.1:8888 - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.2.2:8888 - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.3.1:8888 - ESTAB 0 0 172.16.254.254%eth1:8888 172.16.3.2:8888 LISTEN 0 0 127.0.0.1:4321 *:* - ESTAB 0 0 127.0.0.1%lo:4321 127.0.0.1:1234 The entries with '- ESTAB' are the assocs, some of them may belong to the same endpoint. So we will dump the parent endpoint first, like the entry with 'LISTEN'. then dump the assocs. ep and assocs entries will be dumped in right order so that ss can show them in tree format easily. Besides, this patchset also simplifies sctp proc codes, cause it has some similar codes with sctp diag in sctp transport traversal. v1->v2: 1. inet_diag_get_handler needs to return it as const. 2. merge 5/7 into 2/7 of v1. v2->v3: do some improvements and fixes in patch 1-4, see the details in each patch's comment. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 311b217 + 53fa103 commit 4e811b1

File tree

9 files changed

+863
-112
lines changed

9 files changed

+863
-112
lines changed

include/linux/sctp.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,4 +705,71 @@ typedef struct sctp_auth_chunk {
705705
sctp_authhdr_t auth_hdr;
706706
} __packed sctp_auth_chunk_t;
707707

708+
struct sctp_info {
709+
__u32 sctpi_tag;
710+
__u32 sctpi_state;
711+
__u32 sctpi_rwnd;
712+
__u16 sctpi_unackdata;
713+
__u16 sctpi_penddata;
714+
__u16 sctpi_instrms;
715+
__u16 sctpi_outstrms;
716+
__u32 sctpi_fragmentation_point;
717+
__u32 sctpi_inqueue;
718+
__u32 sctpi_outqueue;
719+
__u32 sctpi_overall_error;
720+
__u32 sctpi_max_burst;
721+
__u32 sctpi_maxseg;
722+
__u32 sctpi_peer_rwnd;
723+
__u32 sctpi_peer_tag;
724+
__u8 sctpi_peer_capable;
725+
__u8 sctpi_peer_sack;
726+
__u16 __reserved1;
727+
728+
/* assoc status info */
729+
__u64 sctpi_isacks;
730+
__u64 sctpi_osacks;
731+
__u64 sctpi_opackets;
732+
__u64 sctpi_ipackets;
733+
__u64 sctpi_rtxchunks;
734+
__u64 sctpi_outofseqtsns;
735+
__u64 sctpi_idupchunks;
736+
__u64 sctpi_gapcnt;
737+
__u64 sctpi_ouodchunks;
738+
__u64 sctpi_iuodchunks;
739+
__u64 sctpi_oodchunks;
740+
__u64 sctpi_iodchunks;
741+
__u64 sctpi_octrlchunks;
742+
__u64 sctpi_ictrlchunks;
743+
744+
/* primary transport info */
745+
struct sockaddr_storage sctpi_p_address;
746+
__s32 sctpi_p_state;
747+
__u32 sctpi_p_cwnd;
748+
__u32 sctpi_p_srtt;
749+
__u32 sctpi_p_rto;
750+
__u32 sctpi_p_hbinterval;
751+
__u32 sctpi_p_pathmaxrxt;
752+
__u32 sctpi_p_sackdelay;
753+
__u32 sctpi_p_sackfreq;
754+
__u32 sctpi_p_ssthresh;
755+
__u32 sctpi_p_partial_bytes_acked;
756+
__u32 sctpi_p_flight_size;
757+
__u16 sctpi_p_error;
758+
__u16 __reserved2;
759+
760+
/* sctp sock info */
761+
__u32 sctpi_s_autoclose;
762+
__u32 sctpi_s_adaptation_ind;
763+
__u32 sctpi_s_pd_point;
764+
__u8 sctpi_s_nodelay;
765+
__u8 sctpi_s_disable_fragments;
766+
__u8 sctpi_s_v4mapped;
767+
__u8 sctpi_s_frag_interleave;
768+
};
769+
770+
struct sctp_infox {
771+
struct sctp_info *sctpinfo;
772+
struct sctp_association *asoc;
773+
};
774+
708775
#endif /* __LINUX_SCTP_H__ */

include/net/sctp/sctp.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,22 @@ extern struct percpu_counter sctp_sockets_allocated;
116116
int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
117117
struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
118118

119+
int sctp_transport_walk_start(struct rhashtable_iter *iter);
120+
void sctp_transport_walk_stop(struct rhashtable_iter *iter);
121+
struct sctp_transport *sctp_transport_get_next(struct net *net,
122+
struct rhashtable_iter *iter);
123+
struct sctp_transport *sctp_transport_get_idx(struct net *net,
124+
struct rhashtable_iter *iter, int pos);
125+
int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
126+
struct net *net,
127+
const union sctp_addr *laddr,
128+
const union sctp_addr *paddr, void *p);
129+
int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *),
130+
struct net *net, int pos, void *p);
131+
int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p);
132+
int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc,
133+
struct sctp_info *info);
134+
119135
/*
120136
* sctp/primitive.c
121137
*/

include/uapi/linux/inet_diag.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ enum {
113113
INET_DIAG_DCTCPINFO,
114114
INET_DIAG_PROTOCOL, /* response attribute only */
115115
INET_DIAG_SKV6ONLY,
116+
INET_DIAG_LOCALS,
117+
INET_DIAG_PEERS,
116118
};
117119

118120
#define INET_DIAG_MAX INET_DIAG_SKV6ONLY

net/ipv4/inet_diag.c

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static void inet_diag_unlock_handler(const struct inet_diag_handler *handler)
6666
mutex_unlock(&inet_diag_table_mutex);
6767
}
6868

69-
static void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk)
69+
void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk)
7070
{
7171
r->idiag_family = sk->sk_family;
7272

@@ -89,6 +89,7 @@ static void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk)
8989
r->id.idiag_dst[0] = sk->sk_daddr;
9090
}
9191
}
92+
EXPORT_SYMBOL_GPL(inet_diag_msg_common_fill);
9293

9394
static size_t inet_sk_attr_size(void)
9495
{
@@ -104,13 +105,50 @@ static size_t inet_sk_attr_size(void)
104105
+ 64;
105106
}
106107

108+
int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
109+
struct inet_diag_msg *r, int ext,
110+
struct user_namespace *user_ns)
111+
{
112+
const struct inet_sock *inet = inet_sk(sk);
113+
114+
if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
115+
goto errout;
116+
117+
/* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
118+
* hence this needs to be included regardless of socket family.
119+
*/
120+
if (ext & (1 << (INET_DIAG_TOS - 1)))
121+
if (nla_put_u8(skb, INET_DIAG_TOS, inet->tos) < 0)
122+
goto errout;
123+
124+
#if IS_ENABLED(CONFIG_IPV6)
125+
if (r->idiag_family == AF_INET6) {
126+
if (ext & (1 << (INET_DIAG_TCLASS - 1)))
127+
if (nla_put_u8(skb, INET_DIAG_TCLASS,
128+
inet6_sk(sk)->tclass) < 0)
129+
goto errout;
130+
131+
if (((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
132+
nla_put_u8(skb, INET_DIAG_SKV6ONLY, ipv6_only_sock(sk)))
133+
goto errout;
134+
}
135+
#endif
136+
137+
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
138+
r->idiag_inode = sock_i_ino(sk);
139+
140+
return 0;
141+
errout:
142+
return 1;
143+
}
144+
EXPORT_SYMBOL_GPL(inet_diag_msg_attrs_fill);
145+
107146
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
108147
struct sk_buff *skb, const struct inet_diag_req_v2 *req,
109148
struct user_namespace *user_ns,
110149
u32 portid, u32 seq, u16 nlmsg_flags,
111150
const struct nlmsghdr *unlh)
112151
{
113-
const struct inet_sock *inet = inet_sk(sk);
114152
const struct tcp_congestion_ops *ca_ops;
115153
const struct inet_diag_handler *handler;
116154
int ext = req->idiag_ext;
@@ -135,32 +173,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
135173
r->idiag_timer = 0;
136174
r->idiag_retrans = 0;
137175

138-
if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
176+
if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns))
139177
goto errout;
140178

141-
/* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
142-
* hence this needs to be included regardless of socket family.
143-
*/
144-
if (ext & (1 << (INET_DIAG_TOS - 1)))
145-
if (nla_put_u8(skb, INET_DIAG_TOS, inet->tos) < 0)
146-
goto errout;
147-
148-
#if IS_ENABLED(CONFIG_IPV6)
149-
if (r->idiag_family == AF_INET6) {
150-
if (ext & (1 << (INET_DIAG_TCLASS - 1)))
151-
if (nla_put_u8(skb, INET_DIAG_TCLASS,
152-
inet6_sk(sk)->tclass) < 0)
153-
goto errout;
154-
155-
if (((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
156-
nla_put_u8(skb, INET_DIAG_SKV6ONLY, ipv6_only_sock(sk)))
157-
goto errout;
158-
}
159-
#endif
160-
161-
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
162-
r->idiag_inode = sock_i_ino(sk);
163-
164179
if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
165180
struct inet_diag_meminfo minfo = {
166181
.idiag_rmem = sk_rmem_alloc_get(sk),

net/sctp/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,9 @@ config SCTP_COOKIE_HMAC_SHA1
9999
select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1
100100
select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1
101101

102+
config INET_SCTP_DIAG
103+
depends on INET_DIAG
104+
def_tristate INET_DIAG
105+
102106

103107
endif # IP_SCTP

net/sctp/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
obj-$(CONFIG_IP_SCTP) += sctp.o
66
obj-$(CONFIG_NET_SCTPPROBE) += sctp_probe.o
7+
obj-$(CONFIG_INET_SCTP_DIAG) += sctp_diag.o
78

89
sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
910
protocol.o endpointola.o associola.o \

net/sctp/proc.c

Lines changed: 19 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -280,83 +280,38 @@ void sctp_eps_proc_exit(struct net *net)
280280
struct sctp_ht_iter {
281281
struct seq_net_private p;
282282
struct rhashtable_iter hti;
283+
int start_fail;
283284
};
284285

285-
static struct sctp_transport *sctp_transport_get_next(struct seq_file *seq)
286+
static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos)
286287
{
287288
struct sctp_ht_iter *iter = seq->private;
288-
struct sctp_transport *t;
289-
290-
t = rhashtable_walk_next(&iter->hti);
291-
for (; t; t = rhashtable_walk_next(&iter->hti)) {
292-
if (IS_ERR(t)) {
293-
if (PTR_ERR(t) == -EAGAIN)
294-
continue;
295-
break;
296-
}
289+
int err = sctp_transport_walk_start(&iter->hti);
297290

298-
if (net_eq(sock_net(t->asoc->base.sk), seq_file_net(seq)) &&
299-
t->asoc->peer.primary_path == t)
300-
break;
291+
if (err) {
292+
iter->start_fail = 1;
293+
return ERR_PTR(err);
301294
}
302295

303-
return t;
296+
return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos);
304297
}
305298

306-
static struct sctp_transport *sctp_transport_get_idx(struct seq_file *seq,
307-
loff_t pos)
308-
{
309-
void *obj = SEQ_START_TOKEN;
310-
311-
while (pos && (obj = sctp_transport_get_next(seq)) && !IS_ERR(obj))
312-
pos--;
313-
314-
return obj;
315-
}
316-
317-
static int sctp_transport_walk_start(struct seq_file *seq)
299+
static void sctp_transport_seq_stop(struct seq_file *seq, void *v)
318300
{
319301
struct sctp_ht_iter *iter = seq->private;
320-
int err;
321-
322-
err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti,
323-
GFP_KERNEL);
324-
if (err)
325-
return err;
326-
327-
err = rhashtable_walk_start(&iter->hti);
328302

329-
return err == -EAGAIN ? 0 : err;
303+
if (iter->start_fail)
304+
return;
305+
sctp_transport_walk_stop(&iter->hti);
330306
}
331307

332-
static void sctp_transport_walk_stop(struct seq_file *seq)
308+
static void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos)
333309
{
334310
struct sctp_ht_iter *iter = seq->private;
335311

336-
rhashtable_walk_stop(&iter->hti);
337-
rhashtable_walk_exit(&iter->hti);
338-
}
339-
340-
static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
341-
{
342-
int err = sctp_transport_walk_start(seq);
343-
344-
if (err)
345-
return ERR_PTR(err);
346-
347-
return sctp_transport_get_idx(seq, *pos);
348-
}
349-
350-
static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
351-
{
352-
sctp_transport_walk_stop(seq);
353-
}
354-
355-
static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
356-
{
357312
++*pos;
358313

359-
return sctp_transport_get_next(seq);
314+
return sctp_transport_get_next(seq_file_net(seq), &iter->hti);
360315
}
361316

362317
/* Display sctp associations (/proc/net/sctp/assocs). */
@@ -417,9 +372,9 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
417372
}
418373

419374
static const struct seq_operations sctp_assoc_ops = {
420-
.start = sctp_assocs_seq_start,
421-
.next = sctp_assocs_seq_next,
422-
.stop = sctp_assocs_seq_stop,
375+
.start = sctp_transport_seq_start,
376+
.next = sctp_transport_seq_next,
377+
.stop = sctp_transport_seq_stop,
423378
.show = sctp_assocs_seq_show,
424379
};
425380

@@ -456,28 +411,6 @@ void sctp_assocs_proc_exit(struct net *net)
456411
remove_proc_entry("assocs", net->sctp.proc_net_sctp);
457412
}
458413

459-
static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
460-
{
461-
int err = sctp_transport_walk_start(seq);
462-
463-
if (err)
464-
return ERR_PTR(err);
465-
466-
return sctp_transport_get_idx(seq, *pos);
467-
}
468-
469-
static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
470-
{
471-
++*pos;
472-
473-
return sctp_transport_get_next(seq);
474-
}
475-
476-
static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
477-
{
478-
sctp_transport_walk_stop(seq);
479-
}
480-
481414
static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
482415
{
483416
struct sctp_association *assoc;
@@ -551,9 +484,9 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
551484
}
552485

553486
static const struct seq_operations sctp_remaddr_ops = {
554-
.start = sctp_remaddr_seq_start,
555-
.next = sctp_remaddr_seq_next,
556-
.stop = sctp_remaddr_seq_stop,
487+
.start = sctp_transport_seq_start,
488+
.next = sctp_transport_seq_next,
489+
.stop = sctp_transport_seq_stop,
557490
.show = sctp_remaddr_seq_show,
558491
};
559492

0 commit comments

Comments
 (0)