diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 12 | 
1 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 711d209f9124..18daddc6001c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -443,6 +443,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,  {  	struct inet_request_sock *ireq = inet_rsk(req);  	struct ipv6_pinfo *np = inet6_sk(sk); +	struct ipv6_txoptions *opt;  	struct flowi6 *fl6 = &fl->u.ip6;  	struct sk_buff *skb;  	int err = -ENOMEM; @@ -463,8 +464,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,  			fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));  		rcu_read_lock(); -		err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), -			       np->tclass); +		opt = ireq->ipv6_opt; +		if (!opt) +			opt = rcu_dereference(np->opt); +		err = ip6_xmit(sk, skb, fl6, opt, np->tclass);  		rcu_read_unlock();  		err = net_xmit_eval(err);  	} @@ -476,6 +479,7 @@ done:  static void tcp_v6_reqsk_destructor(struct request_sock *req)  { +	kfree(inet_rsk(req)->ipv6_opt);  	kfree_skb(inet_rsk(req)->pktopts);  } @@ -1107,7 +1111,9 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *  	   but we make one more one thing there: reattach optmem  	   to newsk.  	 */ -	opt = rcu_dereference(np->opt); +	opt = ireq->ipv6_opt; +	if (!opt) +		opt = rcu_dereference(np->opt);  	if (opt) {  		opt = ipv6_dup_options(newsk, opt);  		RCU_INIT_POINTER(newnp->opt, opt);  | 
