diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 124 | 
1 files changed, 12 insertions, 112 deletions
| diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 26175bffbaa0..6565cf55eb1e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -77,9 +77,6 @@ static void	tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,  				      struct request_sock *req);  static int	tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); -static void	__tcp_v6_send_check(struct sk_buff *skb, -				    const struct in6_addr *saddr, -				    const struct in6_addr *daddr);  static const struct inet_connection_sock_af_ops ipv6_mapped;  static const struct inet_connection_sock_af_ops ipv6_specific; @@ -119,14 +116,6 @@ static void tcp_v6_hash(struct sock *sk)  	}  } -static __inline__ __sum16 tcp_v6_check(int len, -				   const struct in6_addr *saddr, -				   const struct in6_addr *daddr, -				   __wsum base) -{ -	return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); -} -  static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)  {  	return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, @@ -306,7 +295,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,  	if (err)  		goto late_failure; -	if (!tp->write_seq) +	if (!tp->write_seq && likely(!tp->repair))  		tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,  							     np->daddr.s6_addr32,  							     inet->inet_sport, @@ -495,9 +484,12 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,  			     struct request_values *rvp)  {  	struct flowi6 fl6; +	int res; -	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); -	return tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0); +	res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0); +	if (!res) +		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); +	return res;  }  static void tcp_v6_reqsk_destructor(struct request_sock *req) @@ -719,94 +711,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {  };  #endif -static void __tcp_v6_send_check(struct sk_buff *skb, -				const struct in6_addr *saddr, const struct in6_addr *daddr) -{ -	struct tcphdr *th = tcp_hdr(skb); - -	if (skb->ip_summed == CHECKSUM_PARTIAL) { -		th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); -		skb->csum_start = skb_transport_header(skb) - skb->head; -		skb->csum_offset = offsetof(struct tcphdr, check); -	} else { -		th->check = tcp_v6_check(skb->len, saddr, daddr, -					 csum_partial(th, th->doff << 2, -						      skb->csum)); -	} -} - -static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) -{ -	struct ipv6_pinfo *np = inet6_sk(sk); - -	__tcp_v6_send_check(skb, &np->saddr, &np->daddr); -} - -static int tcp_v6_gso_send_check(struct sk_buff *skb) -{ -	const struct ipv6hdr *ipv6h; -	struct tcphdr *th; - -	if (!pskb_may_pull(skb, sizeof(*th))) -		return -EINVAL; - -	ipv6h = ipv6_hdr(skb); -	th = tcp_hdr(skb); - -	th->check = 0; -	skb->ip_summed = CHECKSUM_PARTIAL; -	__tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); -	return 0; -} - -static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, -					 struct sk_buff *skb) -{ -	const struct ipv6hdr *iph = skb_gro_network_header(skb); -	__wsum wsum; -	__sum16 sum; - -	switch (skb->ip_summed) { -	case CHECKSUM_COMPLETE: -		if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, -				  skb->csum)) { -			skb->ip_summed = CHECKSUM_UNNECESSARY; -			break; -		} -flush: -		NAPI_GRO_CB(skb)->flush = 1; -		return NULL; - -	case CHECKSUM_NONE: -		wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, -						    skb_gro_len(skb), -						    IPPROTO_TCP, 0)); -		sum = csum_fold(skb_checksum(skb, -					     skb_gro_offset(skb), -					     skb_gro_len(skb), -					     wsum)); -		if (sum) -			goto flush; - -		skb->ip_summed = CHECKSUM_UNNECESSARY; -		break; -	} - -	return tcp_gro_receive(head, skb); -} - -static int tcp6_gro_complete(struct sk_buff *skb) -{ -	const struct ipv6hdr *iph = ipv6_hdr(skb); -	struct tcphdr *th = tcp_hdr(skb); - -	th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), -				  &iph->saddr, &iph->daddr, 0); -	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - -	return tcp_gro_complete(skb); -} -  static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,  				 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)  { @@ -1364,7 +1268,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,  	tcp_initialize_rcv_mss(newsk);  	tcp_synack_rtt_meas(newsk, req); -	newtp->total_retrans = req->retrans; +	newtp->total_retrans = req->num_retrans;  	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;  	newinet->inet_rcv_saddr = LOOPBACK4_IPV6; @@ -1741,11 +1645,11 @@ static void tcp_v6_early_demux(struct sk_buff *skb)  		skb->destructor = sock_edemux;  		if (sk->sk_state != TCP_TIME_WAIT) {  			struct dst_entry *dst = sk->sk_rx_dst; -			struct inet_sock *icsk = inet_sk(sk); +  			if (dst)  				dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);  			if (dst && -			    icsk->rx_dst_ifindex == skb->skb_iif) +			    inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)  				skb_dst_set_noref(skb, dst);  		}  	} @@ -1866,7 +1770,7 @@ static void get_openreq6(struct seq_file *seq,  		   0,0, /* could print option size, but that is af dependent. */  		   1,   /* timers active (only the expire timer) */  		   jiffies_to_clock_t(ttd), -		   req->retrans, +		   req->num_timeout,  		   from_kuid_munged(seq_user_ns(seq), uid),  		   0,  /* non standard timer */  		   0, /* open_requests have no inode */ @@ -2063,10 +1967,6 @@ static const struct inet6_protocol tcpv6_protocol = {  	.early_demux	=	tcp_v6_early_demux,  	.handler	=	tcp_v6_rcv,  	.err_handler	=	tcp_v6_err, -	.gso_send_check	=	tcp_v6_gso_send_check, -	.gso_segment	=	tcp_tso_segment, -	.gro_receive	=	tcp6_gro_receive, -	.gro_complete	=	tcp6_gro_complete,  	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,  }; @@ -2121,10 +2021,10 @@ int __init tcpv6_init(void)  out:  	return ret; -out_tcpv6_protocol: -	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);  out_tcpv6_protosw:  	inet6_unregister_protosw(&tcpv6_protosw); +out_tcpv6_protocol: +	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);  	goto out;  } |