aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r--net/sctp/protocol.c25
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
504out_unlock: 499out_unlock:
505 sctp_read_unlock(addr_lock); 500 rcu_read_unlock();
506out: 501out:
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",