diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 22 | 
1 files changed, 12 insertions, 10 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6b8a8a9091fa..4ad8edb46f7c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -462,8 +462,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,  		if (np->repflow && ireq->pktopts)  			fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); +		rcu_read_lock();  		err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),  			       np->tclass); +		rcu_read_unlock();  		err = net_xmit_eval(err);  	} @@ -854,7 +856,9 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)  #ifdef CONFIG_TCP_MD5SIG  	hash_location = tcp_parse_md5sig_option(th); -	if (!sk && hash_location) { +	if (sk && sk_fullsock(sk)) { +		key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr); +	} else if (hash_location) {  		/*  		 * active side is lost. Try to find listening socket through  		 * source port, and then find md5 key through listening socket. @@ -877,8 +881,6 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)  		genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb);  		if (genhash || memcmp(hash_location, newhash, 16) != 0)  			goto release_sk1; -	} else { -		key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;  	}  #endif @@ -1135,7 +1137,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *  		 */  		tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,  			       AF_INET6, key->key, key->keylen, -			       sk_gfp_atomic(sk, GFP_ATOMIC)); +			       sk_gfp_mask(sk, GFP_ATOMIC));  	}  #endif @@ -1151,7 +1153,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *  		/* Clone pktoptions received with SYN, if we own the req */  		if (ireq->pktopts) {  			newnp->pktoptions = skb_clone(ireq->pktopts, -						      sk_gfp_atomic(sk, GFP_ATOMIC)); +						      sk_gfp_mask(sk, GFP_ATOMIC));  			consume_skb(ireq->pktopts);  			ireq->pktopts = NULL;  			if (newnp->pktoptions) @@ -1217,7 +1219,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)  					       --ANK (980728)  	 */  	if (np->rxopt.all) -		opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); +		opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC));  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */  		struct dst_entry *dst = sk->sk_rx_dst; @@ -1516,7 +1518,9 @@ do_time_wait:  		break;  	case TCP_TW_RST:  		tcp_v6_restore_cb(skb); -		goto no_tcp_socket; +		tcp_v6_send_reset(sk, skb); +		inet_twsk_deschedule_put(inet_twsk(sk)); +		goto discard_it;  	case TCP_TW_SUCCESS:  		;  	} @@ -1885,10 +1889,8 @@ struct proto tcpv6_prot = {  	.compat_setsockopt	= compat_tcp_setsockopt,  	.compat_getsockopt	= compat_tcp_getsockopt,  #endif -#ifdef CONFIG_MEMCG_KMEM -	.proto_cgroup		= tcp_proto_cgroup, -#endif  	.clear_sk		= tcp_v6_clear_sk, +	.diag_destroy		= tcp_abort,  };  static const struct inet6_protocol tcpv6_protocol = {  | 
