diff options
| author | Linus Walleij <linus.walleij@linaro.org> | 2013-10-08 13:27:11 +0200 | 
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2013-10-08 13:27:11 +0200 | 
| commit | bfabb59433fc18ff78d2818e10e212d0f85d56ae (patch) | |
| tree | dd7cbead179c09c62627a84c16c802d99095ba6e /net/sctp/ipv6.c | |
| parent | 6a08a92ec45782e5543addf5f8785e2560a078f6 (diff) | |
| parent | d0e639c9e06d44e713170031fe05fb60ebe680af (diff) | |
Merge tag 'v3.12-rc4' into devel
Linux 3.12-rc4
Diffstat (limited to 'net/sctp/ipv6.c')
| -rw-r--r-- | net/sctp/ipv6.c | 44 | 
1 files changed, 14 insertions, 30 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index da613ceae28..e7b2d4fe2b6 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -183,7 +183,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  		break;  	case NDISC_REDIRECT:  		sctp_icmp_redirect(sk, transport, skb); -		break; +		goto out_unlock;  	default:  		break;  	} @@ -204,44 +204,23 @@ out:  		in6_dev_put(idev);  } -/* Based on tcp_v6_xmit() in tcp_ipv6.c. */  static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)  {  	struct sock *sk = skb->sk;  	struct ipv6_pinfo *np = inet6_sk(sk); -	struct flowi6 fl6; - -	memset(&fl6, 0, sizeof(fl6)); - -	fl6.flowi6_proto = sk->sk_protocol; - -	/* Fill in the dest address from the route entry passed with the skb -	 * and the source address from the transport. -	 */ -	fl6.daddr = transport->ipaddr.v6.sin6_addr; -	fl6.saddr = transport->saddr.v6.sin6_addr; - -	fl6.flowlabel = np->flow_label; -	IP6_ECN_flow_xmit(sk, fl6.flowlabel); -	if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL) -		fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id; -	else -		fl6.flowi6_oif = sk->sk_bound_dev_if; - -	if (np->opt && np->opt->srcrt) { -		struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -		fl6.daddr = *rt0->addr; -	} +	struct flowi6 *fl6 = &transport->fl.u.ip6;  	pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, -		 skb->len, &fl6.saddr, &fl6.daddr); +		 skb->len, &fl6->saddr, &fl6->daddr); -	SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); +	IP6_ECN_flow_xmit(sk, fl6->flowlabel);  	if (!(transport->param_flags & SPP_PMTUD_ENABLE))  		skb->local_df = 1; -	return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); +	SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); + +	return ip6_xmit(sk, skb, fl6, np->opt, np->tclass);  }  /* Returns the dst cache entry for the given source and destination ip @@ -254,10 +233,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,  	struct dst_entry *dst = NULL;  	struct flowi6 *fl6 = &fl->u.ip6;  	struct sctp_bind_addr *bp; +	struct ipv6_pinfo *np = inet6_sk(sk);  	struct sctp_sockaddr_entry *laddr;  	union sctp_addr *baddr = NULL;  	union sctp_addr *daddr = &t->ipaddr;  	union sctp_addr dst_saddr; +	struct in6_addr *final_p, final;  	__u8 matchlen = 0;  	__u8 bmatchlen;  	sctp_scope_t scope; @@ -281,7 +262,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,  		pr_debug("src=%pI6 - ", &fl6->saddr);  	} -	dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); +	final_p = fl6_update_dst(fl6, np->opt, &final); +	dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);  	if (!asoc || saddr)  		goto out; @@ -333,10 +315,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,  		}  	}  	rcu_read_unlock(); +  	if (baddr) {  		fl6->saddr = baddr->v6.sin6_addr;  		fl6->fl6_sport = baddr->v6.sin6_port; -		dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); +		final_p = fl6_update_dst(fl6, np->opt, &final); +		dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);  	}  out:  | 
