aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sctp/sctp_diag.c32
-rw-r--r--net/sctp/socket.c40
2 files changed, 34 insertions, 38 deletions
diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c
index e99518e79b52..7008a992749b 100644
--- a/net/sctp/sctp_diag.c
+++ b/net/sctp/sctp_diag.c
@@ -279,9 +279,11 @@ out:
279 return err; 279 return err;
280} 280}
281 281
282static int sctp_sock_dump(struct sock *sk, void *p) 282static int sctp_sock_dump(struct sctp_transport *tsp, void *p)
283{ 283{
284 struct sctp_endpoint *ep = tsp->asoc->ep;
284 struct sctp_comm_param *commp = p; 285 struct sctp_comm_param *commp = p;
286 struct sock *sk = ep->base.sk;
285 struct sk_buff *skb = commp->skb; 287 struct sk_buff *skb = commp->skb;
286 struct netlink_callback *cb = commp->cb; 288 struct netlink_callback *cb = commp->cb;
287 const struct inet_diag_req_v2 *r = commp->r; 289 const struct inet_diag_req_v2 *r = commp->r;
@@ -289,9 +291,7 @@ static int sctp_sock_dump(struct sock *sk, void *p)
289 int err = 0; 291 int err = 0;
290 292
291 lock_sock(sk); 293 lock_sock(sk);
292 if (!sctp_sk(sk)->ep) 294 list_for_each_entry(assoc, &ep->asocs, asocs) {
293 goto release;
294 list_for_each_entry(assoc, &sctp_sk(sk)->ep->asocs, asocs) {
295 if (cb->args[4] < cb->args[1]) 295 if (cb->args[4] < cb->args[1])
296 goto next; 296 goto next;
297 297
@@ -327,40 +327,30 @@ next:
327 cb->args[4]++; 327 cb->args[4]++;
328 } 328 }
329 cb->args[1] = 0; 329 cb->args[1] = 0;
330 cb->args[2]++;
331 cb->args[3] = 0; 330 cb->args[3] = 0;
332 cb->args[4] = 0; 331 cb->args[4] = 0;
333release: 332release:
334 release_sock(sk); 333 release_sock(sk);
335 sock_put(sk);
336 return err; 334 return err;
337} 335}
338 336
339static int sctp_get_sock(struct sctp_transport *tsp, void *p) 337static int sctp_sock_filter(struct sctp_transport *tsp, void *p)
340{ 338{
341 struct sctp_endpoint *ep = tsp->asoc->ep; 339 struct sctp_endpoint *ep = tsp->asoc->ep;
342 struct sctp_comm_param *commp = p; 340 struct sctp_comm_param *commp = p;
343 struct sock *sk = ep->base.sk; 341 struct sock *sk = ep->base.sk;
344 struct netlink_callback *cb = commp->cb;
345 const struct inet_diag_req_v2 *r = commp->r; 342 const struct inet_diag_req_v2 *r = commp->r;
346 struct sctp_association *assoc = 343 struct sctp_association *assoc =
347 list_entry(ep->asocs.next, struct sctp_association, asocs); 344 list_entry(ep->asocs.next, struct sctp_association, asocs);
348 345
349 /* find the ep only once through the transports by this condition */ 346 /* find the ep only once through the transports by this condition */
350 if (tsp->asoc != assoc) 347 if (tsp->asoc != assoc)
351 goto out; 348 return 0;
352 349
353 if (r->sdiag_family != AF_UNSPEC && sk->sk_family != r->sdiag_family) 350 if (r->sdiag_family != AF_UNSPEC && sk->sk_family != r->sdiag_family)
354 goto out; 351 return 0;
355
356 sock_hold(sk);
357 cb->args[5] = (long)sk;
358 352
359 return 1; 353 return 1;
360
361out:
362 cb->args[2]++;
363 return 0;
364} 354}
365 355
366static int sctp_ep_dump(struct sctp_endpoint *ep, void *p) 356static int sctp_ep_dump(struct sctp_endpoint *ep, void *p)
@@ -503,12 +493,8 @@ skip:
503 if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE))) 493 if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE)))
504 goto done; 494 goto done;
505 495
506next: 496 sctp_for_each_transport(sctp_sock_filter, sctp_sock_dump,
507 cb->args[5] = 0; 497 net, (int *)&cb->args[2], &commp);
508 sctp_for_each_transport(sctp_get_sock, net, cb->args[2], &commp);
509
510 if (cb->args[5] && !sctp_sock_dump((struct sock *)cb->args[5], &commp))
511 goto next;
512 498
513done: 499done:
514 cb->args[1] = cb->args[4]; 500 cb->args[1] = cb->args[4];
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1b00a1e09b93..d4730ada7f32 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4658,29 +4658,39 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
4658EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); 4658EXPORT_SYMBOL_GPL(sctp_transport_lookup_process);
4659 4659
4660int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), 4660int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *),
4661 struct net *net, int pos, void *p) { 4661 int (*cb_done)(struct sctp_transport *, void *),
4662 struct net *net, int *pos, void *p) {
4662 struct rhashtable_iter hti; 4663 struct rhashtable_iter hti;
4663 void *obj; 4664 struct sctp_transport *tsp;
4664 int err; 4665 int ret;
4665
4666 err = sctp_transport_walk_start(&hti);
4667 if (err)
4668 return err;
4669 4666
4670 obj = sctp_transport_get_idx(net, &hti, pos + 1); 4667again:
4671 for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) { 4668 ret = sctp_transport_walk_start(&hti);
4672 struct sctp_transport *transport = obj; 4669 if (ret)
4670 return ret;
4673 4671
4674 if (!sctp_transport_hold(transport)) 4672 tsp = sctp_transport_get_idx(net, &hti, *pos + 1);
4673 for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) {
4674 if (!sctp_transport_hold(tsp))
4675 continue; 4675 continue;
4676 err = cb(transport, p); 4676 ret = cb(tsp, p);
4677 sctp_transport_put(transport); 4677 if (ret)
4678 if (err)
4679 break; 4678 break;
4679 (*pos)++;
4680 sctp_transport_put(tsp);
4680 } 4681 }
4681 sctp_transport_walk_stop(&hti); 4682 sctp_transport_walk_stop(&hti);
4682 4683
4683 return err; 4684 if (ret) {
4685 if (cb_done && !cb_done(tsp, p)) {
4686 (*pos)++;
4687 sctp_transport_put(tsp);
4688 goto again;
4689 }
4690 sctp_transport_put(tsp);
4691 }
4692
4693 return ret;
4684} 4694}
4685EXPORT_SYMBOL_GPL(sctp_for_each_transport); 4695EXPORT_SYMBOL_GPL(sctp_for_each_transport);
4686 4696