Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 246999
b: refs/heads/master
c: 6250341
h: refs/heads/master
i:
  246997: 140c198
  246995: f610664
  246991: 0e110c5
v: v3
  • Loading branch information
Weixing Shi authored and David S. Miller committed Apr 27, 2011
1 parent 59d7437 commit ac88488
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 66e6961c8e53c0c0079d5b67faf9b7fe33525892
refs/heads/master: 625034113bd45c71fb9e329f52f25fef9e6993a3
44 changes: 43 additions & 1 deletion trunk/net/sctp/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@

#include <asm/uaccess.h>

static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
union sctp_addr *s2);

/* Event handler for inet6 address addition/deletion events.
* The sctp_local_addr_list needs to be protocted by a spin lock since
* multiple notifiers (say IPv4 and IPv6) may be running at the same
Expand Down Expand Up @@ -244,8 +247,14 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
union sctp_addr *daddr,
union sctp_addr *saddr)
{
struct dst_entry *dst;
struct dst_entry *dst = NULL;
struct flowi6 fl6;
struct sctp_bind_addr *bp;
struct sctp_sockaddr_entry *laddr;
union sctp_addr *baddr = NULL;
__u8 matchlen = 0;
__u8 bmatchlen;
sctp_scope_t scope;

memset(&fl6, 0, sizeof(fl6));
ipv6_addr_copy(&fl6.daddr, &daddr->v6.sin6_addr);
Expand All @@ -261,6 +270,39 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
}

dst = ip6_route_output(&init_net, NULL, &fl6);
if (!asoc || saddr)
goto out;

if (dst->error) {
dst_release(dst);
dst = NULL;
bp = &asoc->base.bind_addr;
scope = sctp_scope(daddr);
/* Walk through the bind address list and try to get a dst that
* matches a bind address as the source address.
*/
rcu_read_lock();
list_for_each_entry_rcu(laddr, &bp->address_list, list) {
if (!laddr->valid)
continue;
if ((laddr->state == SCTP_ADDR_SRC) &&
(laddr->a.sa.sa_family == AF_INET6) &&
(scope <= sctp_scope(&laddr->a))) {
bmatchlen = sctp_v6_addr_match_len(daddr,
&laddr->a);
if (!baddr || (matchlen < bmatchlen)) {
baddr = &laddr->a;
matchlen = bmatchlen;
}
}
}
rcu_read_unlock();
if (baddr) {
ipv6_addr_copy(&fl6.saddr, &baddr->v6.sin6_addr);
dst = ip6_route_output(&init_net, NULL, &fl6);
}
}
out:
if (!dst->error) {
struct rt6_info *rt;
rt = (struct rt6_info *)dst;
Expand Down

0 comments on commit ac88488

Please sign in to comment.