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", |
