diff options
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r-- | net/sctp/protocol.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 7ee120e85913..3d036cdfae41 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -224,7 +224,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, | |||
224 | (copy_flags & SCTP_ADDR6_ALLOWED) && | 224 | (copy_flags & SCTP_ADDR6_ALLOWED) && |
225 | (copy_flags & SCTP_ADDR6_PEERSUPP)))) { | 225 | (copy_flags & SCTP_ADDR6_PEERSUPP)))) { |
226 | error = sctp_add_bind_addr(bp, &addr->a, 1, | 226 | error = sctp_add_bind_addr(bp, &addr->a, 1, |
227 | GFP_ATOMIC); | 227 | GFP_ATOMIC); |
228 | if (error) | 228 | if (error) |
229 | goto end_copy; | 229 | goto end_copy; |
230 | } | 230 | } |
@@ -428,9 +428,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
428 | struct rtable *rt; | 428 | struct rtable *rt; |
429 | struct flowi fl; | 429 | struct flowi fl; |
430 | struct sctp_bind_addr *bp; | 430 | struct sctp_bind_addr *bp; |
431 | rwlock_t *addr_lock; | ||
432 | struct sctp_sockaddr_entry *laddr; | 431 | struct sctp_sockaddr_entry *laddr; |
433 | struct list_head *pos; | ||
434 | struct dst_entry *dst = NULL; | 432 | struct dst_entry *dst = NULL; |
435 | union sctp_addr dst_saddr; | 433 | union sctp_addr dst_saddr; |
436 | 434 | ||
@@ -459,23 +457,20 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
459 | goto out; | 457 | goto out; |
460 | 458 | ||
461 | bp = &asoc->base.bind_addr; | 459 | bp = &asoc->base.bind_addr; |
462 | addr_lock = &asoc->base.addr_lock; | ||
463 | 460 | ||
464 | if (dst) { | 461 | if (dst) { |
465 | /* Walk through the bind address list and look for a bind | 462 | /* Walk through the bind address list and look for a bind |
466 | * address that matches the source address of the returned dst. | 463 | * address that matches the source address of the returned dst. |
467 | */ | 464 | */ |
468 | sctp_read_lock(addr_lock); | 465 | rcu_read_lock(); |
469 | list_for_each(pos, &bp->address_list) { | 466 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
470 | laddr = list_entry(pos, struct sctp_sockaddr_entry, | 467 | if (!laddr->valid || !laddr->use_as_src) |
471 | list); | ||
472 | if (!laddr->use_as_src) | ||
473 | continue; | 468 | continue; |
474 | sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); | 469 | sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); |
475 | if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) | 470 | if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) |
476 | goto out_unlock; | 471 | goto out_unlock; |
477 | } | 472 | } |
478 | sctp_read_unlock(addr_lock); | 473 | rcu_read_unlock(); |
479 | 474 | ||
480 | /* None of the bound addresses match the source address of the | 475 | /* None of the bound addresses match the source address of the |
481 | * dst. So release it. | 476 | * dst. So release it. |
@@ -487,10 +482,10 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
487 | /* Walk through the bind address list and try to get a dst that | 482 | /* Walk through the bind address list and try to get a dst that |
488 | * matches a bind address as the source address. | 483 | * matches a bind address as the source address. |
489 | */ | 484 | */ |
490 | sctp_read_lock(addr_lock); | 485 | rcu_read_lock(); |
491 | list_for_each(pos, &bp->address_list) { | 486 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
492 | laddr = list_entry(pos, struct sctp_sockaddr_entry, list); | 487 | if (!laddr->valid) |
493 | 488 | continue; | |
494 | if ((laddr->use_as_src) && | 489 | if ((laddr->use_as_src) && |
495 | (AF_INET == laddr->a.sa.sa_family)) { | 490 | (AF_INET == laddr->a.sa.sa_family)) { |
496 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; | 491 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; |
@@ -502,7 +497,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
502 | } | 497 | } |
503 | 498 | ||
504 | out_unlock: | 499 | out_unlock: |
505 | sctp_read_unlock(addr_lock); | 500 | rcu_read_unlock(); |
506 | out: | 501 | out: |
507 | if (dst) | 502 | if (dst) |
508 | SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n", | 503 | SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n", |