diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 49 | 
1 files changed, 25 insertions, 24 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3f4cba49e9ee..4c3605485b68 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -60,6 +60,7 @@  #include <net/secure_seq.h>  #include <net/hotdata.h>  #include <net/busy_poll.h> +#include <net/rstreason.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> @@ -69,7 +70,8 @@  #include <trace/events/tcp.h> -static void	tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb); +static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb, +			      enum sk_rst_reason reason);  static void	tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,  				      struct request_sock *req); @@ -95,11 +97,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)  	struct dst_entry *dst = skb_dst(skb);  	if (dst && dst_hold_safe(dst)) { -		const struct rt6_info *rt = (const struct rt6_info *)dst; -  		rcu_assign_pointer(sk->sk_rx_dst, dst);  		sk->sk_rx_dst_ifindex = skb->skb_iif; -		sk->sk_rx_dst_cookie = rt6_get_cookie(rt); +		sk->sk_rx_dst_cookie = rt6_get_cookie(dst_rt6_info(dst));  	}  } @@ -793,7 +793,8 @@ clear_hash_nostart:  static void tcp_v6_init_req(struct request_sock *req,  			    const struct sock *sk_listener, -			    struct sk_buff *skb) +			    struct sk_buff *skb, +			    u32 tw_isn)  {  	bool l3_slave = ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags);  	struct inet_request_sock *ireq = inet_rsk(req); @@ -807,7 +808,7 @@ static void tcp_v6_init_req(struct request_sock *req,  	    ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)  		ireq->ir_iif = tcp_v6_iif(skb); -	if (!TCP_SKB_CB(skb)->tcp_tw_isn && +	if (!tw_isn &&  	    (ipv6_opt_accepted(sk_listener, skb, &TCP_SKB_CB(skb)->header.h6) ||  	     np->rxopt.bits.rxinfo ||  	     np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim || @@ -820,9 +821,10 @@ static void tcp_v6_init_req(struct request_sock *req,  static struct dst_entry *tcp_v6_route_req(const struct sock *sk,  					  struct sk_buff *skb,  					  struct flowi *fl, -					  struct request_sock *req) +					  struct request_sock *req, +					  u32 tw_isn)  { -	tcp_v6_init_req(req, sk, skb); +	tcp_v6_init_req(req, sk, skb, tw_isn);  	if (security_inet_conn_request(sk, skb, req))  		return NULL; @@ -1006,7 +1008,8 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32  	kfree_skb(buff);  } -static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) +static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb, +			      enum sk_rst_reason reason)  {  	const struct tcphdr *th = tcp_hdr(skb);  	struct ipv6hdr *ipv6h = ipv6_hdr(skb); @@ -1113,7 +1116,6 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)  	if (sk) {  		oif = sk->sk_bound_dev_if;  		if (sk_fullsock(sk)) { -			trace_tcp_send_reset(sk, skb);  			if (inet6_test_bit(REPFLOW, sk))  				label = ip6_flowlabel(ipv6h);  			priority = READ_ONCE(sk->sk_priority); @@ -1129,6 +1131,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)  			label = ip6_flowlabel(ipv6h);  	} +	trace_tcp_send_reset(sk, skb, reason); +  	tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, 1,  			     ipv6_get_dsfield(ipv6h), label, priority, txhash,  			     &key); @@ -1674,7 +1678,7 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)  	return 0;  reset: -	tcp_v6_send_reset(sk, skb); +	tcp_v6_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));  discard:  	if (opt_skb)  		__kfree_skb(opt_skb); @@ -1738,7 +1742,6 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,  				    skb->len - th->doff*4);  	TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);  	TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); -	TCP_SKB_CB(skb)->tcp_tw_isn = 0;  	TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);  	TCP_SKB_CB(skb)->sacked = 0;  	TCP_SKB_CB(skb)->has_rxtstamp = @@ -1755,6 +1758,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)  	bool refcounted;  	struct sock *sk;  	int ret; +	u32 isn;  	struct net *net = dev_net(skb->dev);  	drop_reason = SKB_DROP_REASON_NOT_SPECIFIED; @@ -1791,7 +1795,6 @@ lookup:  	if (!sk)  		goto no_tcp_socket; -process:  	if (sk->sk_state == TCP_TIME_WAIT)  		goto do_time_wait; @@ -1860,7 +1863,10 @@ process:  		} else {  			drop_reason = tcp_child_process(sk, nsk, skb);  			if (drop_reason) { -				tcp_v6_send_reset(nsk, skb); +				enum sk_rst_reason rst_reason; + +				rst_reason = sk_rst_convert_drop_reason(drop_reason); +				tcp_v6_send_reset(nsk, skb, rst_reason);  				goto discard_and_relse;  			}  			sock_put(sk); @@ -1868,6 +1874,7 @@ process:  		}  	} +process:  	if (static_branch_unlikely(&ip6_min_hopcount)) {  		/* min_hopcount can be changed concurrently from do_ipv6_setsockopt() */  		if (unlikely(hdr->hop_limit < READ_ONCE(tcp_inet6_sk(sk)->min_hopcount))) { @@ -1936,7 +1943,7 @@ csum_error:  bad_packet:  		__TCP_INC_STATS(net, TCP_MIB_INERRS);  	} else { -		tcp_v6_send_reset(NULL, skb); +		tcp_v6_send_reset(NULL, skb, sk_rst_convert_drop_reason(drop_reason));  	}  discard_it: @@ -1964,7 +1971,7 @@ do_time_wait:  		goto csum_error;  	} -	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { +	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn)) {  	case TCP_TW_SYN:  	{  		struct sock *sk2; @@ -1982,6 +1989,7 @@ do_time_wait:  			sk = sk2;  			tcp_v6_restore_cb(skb);  			refcounted = false; +			__this_cpu_write(tcp_tw_isn, isn);  			goto process;  		}  	} @@ -1991,7 +1999,7 @@ do_time_wait:  		tcp_v6_timewait_ack(sk, skb);  		break;  	case TCP_TW_RST: -		tcp_v6_send_reset(sk, skb); +		tcp_v6_send_reset(sk, skb, SK_RST_REASON_TCP_TIMEWAIT_SOCKET);  		inet_twsk_deschedule_put(inet_twsk(sk));  		goto discard_it;  	case TCP_TW_SUCCESS: @@ -2041,7 +2049,6 @@ void tcp_v6_early_demux(struct sk_buff *skb)  static struct timewait_sock_ops tcp6_timewait_sock_ops = {  	.twsk_obj_size	= sizeof(struct tcp6_timewait_sock), -	.twsk_unique	= tcp_twsk_unique,  	.twsk_destructor = tcp_twsk_destructor,  }; @@ -2389,15 +2396,9 @@ static void __net_exit tcpv6_net_exit(struct net *net)  	inet_ctl_sock_destroy(net->ipv6.tcp_sk);  } -static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list) -{ -	tcp_twsk_purge(net_exit_list, AF_INET6); -} -  static struct pernet_operations tcpv6_net_ops = {  	.init	    = tcpv6_net_init,  	.exit	    = tcpv6_net_exit, -	.exit_batch = tcpv6_net_exit_batch,  };  int __init tcpv6_init(void)  |