diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/sctp_diag.c | 32 | ||||
-rw-r--r-- | net/sctp/socket.c | 40 |
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 | ||
282 | static int sctp_sock_dump(struct sock *sk, void *p) | 282 | static 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; |
333 | release: | 332 | release: |
334 | release_sock(sk); | 333 | release_sock(sk); |
335 | sock_put(sk); | ||
336 | return err; | 334 | return err; |
337 | } | 335 | } |
338 | 336 | ||
339 | static int sctp_get_sock(struct sctp_transport *tsp, void *p) | 337 | static 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 | |||
361 | out: | ||
362 | cb->args[2]++; | ||
363 | return 0; | ||
364 | } | 354 | } |
365 | 355 | ||
366 | static int sctp_ep_dump(struct sctp_endpoint *ep, void *p) | 356 | static 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 | ||
506 | next: | 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 | ||
513 | done: | 499 | done: |
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 *), | |||
4658 | EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); | 4658 | EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); |
4659 | 4659 | ||
4660 | int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), | 4660 | int 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); | 4667 | again: |
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 | } |
4685 | EXPORT_SYMBOL_GPL(sctp_for_each_transport); | 4695 | EXPORT_SYMBOL_GPL(sctp_for_each_transport); |
4686 | 4696 | ||