aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c127
1 files changed, 14 insertions, 113 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 26175bffbaa0..93825dd3a7c0 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,
77 struct request_sock *req); 77 struct request_sock *req);
78 78
79static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); 79static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
80static void __tcp_v6_send_check(struct sk_buff *skb,
81 const struct in6_addr *saddr,
82 const struct in6_addr *daddr);
83 80
84static const struct inet_connection_sock_af_ops ipv6_mapped; 81static const struct inet_connection_sock_af_ops ipv6_mapped;
85static const struct inet_connection_sock_af_ops ipv6_specific; 82static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -119,14 +116,6 @@ static void tcp_v6_hash(struct sock *sk)
119 } 116 }
120} 117}
121 118
122static __inline__ __sum16 tcp_v6_check(int len,
123 const struct in6_addr *saddr,
124 const struct in6_addr *daddr,
125 __wsum base)
126{
127 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
128}
129
130static __u32 tcp_v6_init_sequence(const struct sk_buff *skb) 119static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
131{ 120{
132 return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, 121 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,
306 if (err) 295 if (err)
307 goto late_failure; 296 goto late_failure;
308 297
309 if (!tp->write_seq) 298 if (!tp->write_seq && likely(!tp->repair))
310 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, 299 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
311 np->daddr.s6_addr32, 300 np->daddr.s6_addr32,
312 inet->inet_sport, 301 inet->inet_sport,
@@ -495,9 +484,12 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
495 struct request_values *rvp) 484 struct request_values *rvp)
496{ 485{
497 struct flowi6 fl6; 486 struct flowi6 fl6;
487 int res;
498 488
499 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); 489 res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
500 return tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0); 490 if (!res)
491 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
492 return res;
501} 493}
502 494
503static void tcp_v6_reqsk_destructor(struct request_sock *req) 495static 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 = {
719}; 711};
720#endif 712#endif
721 713
722static void __tcp_v6_send_check(struct sk_buff *skb,
723 const struct in6_addr *saddr, const struct in6_addr *daddr)
724{
725 struct tcphdr *th = tcp_hdr(skb);
726
727 if (skb->ip_summed == CHECKSUM_PARTIAL) {
728 th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
729 skb->csum_start = skb_transport_header(skb) - skb->head;
730 skb->csum_offset = offsetof(struct tcphdr, check);
731 } else {
732 th->check = tcp_v6_check(skb->len, saddr, daddr,
733 csum_partial(th, th->doff << 2,
734 skb->csum));
735 }
736}
737
738static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
739{
740 struct ipv6_pinfo *np = inet6_sk(sk);
741
742 __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
743}
744
745static int tcp_v6_gso_send_check(struct sk_buff *skb)
746{
747 const struct ipv6hdr *ipv6h;
748 struct tcphdr *th;
749
750 if (!pskb_may_pull(skb, sizeof(*th)))
751 return -EINVAL;
752
753 ipv6h = ipv6_hdr(skb);
754 th = tcp_hdr(skb);
755
756 th->check = 0;
757 skb->ip_summed = CHECKSUM_PARTIAL;
758 __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
759 return 0;
760}
761
762static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
763 struct sk_buff *skb)
764{
765 const struct ipv6hdr *iph = skb_gro_network_header(skb);
766 __wsum wsum;
767 __sum16 sum;
768
769 switch (skb->ip_summed) {
770 case CHECKSUM_COMPLETE:
771 if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
772 skb->csum)) {
773 skb->ip_summed = CHECKSUM_UNNECESSARY;
774 break;
775 }
776flush:
777 NAPI_GRO_CB(skb)->flush = 1;
778 return NULL;
779
780 case CHECKSUM_NONE:
781 wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
782 skb_gro_len(skb),
783 IPPROTO_TCP, 0));
784 sum = csum_fold(skb_checksum(skb,
785 skb_gro_offset(skb),
786 skb_gro_len(skb),
787 wsum));
788 if (sum)
789 goto flush;
790
791 skb->ip_summed = CHECKSUM_UNNECESSARY;
792 break;
793 }
794
795 return tcp_gro_receive(head, skb);
796}
797
798static int tcp6_gro_complete(struct sk_buff *skb)
799{
800 const struct ipv6hdr *iph = ipv6_hdr(skb);
801 struct tcphdr *th = tcp_hdr(skb);
802
803 th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
804 &iph->saddr, &iph->daddr, 0);
805 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
806
807 return tcp_gro_complete(skb);
808}
809
810static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, 714static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
811 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass) 715 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
812{ 716{
@@ -1364,7 +1268,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1364 1268
1365 tcp_initialize_rcv_mss(newsk); 1269 tcp_initialize_rcv_mss(newsk);
1366 tcp_synack_rtt_meas(newsk, req); 1270 tcp_synack_rtt_meas(newsk, req);
1367 newtp->total_retrans = req->retrans; 1271 newtp->total_retrans = req->num_retrans;
1368 1272
1369 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; 1273 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
1370 newinet->inet_rcv_saddr = LOOPBACK4_IPV6; 1274 newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
@@ -1384,7 +1288,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1384#endif 1288#endif
1385 1289
1386 if (__inet_inherit_port(sk, newsk) < 0) { 1290 if (__inet_inherit_port(sk, newsk) < 0) {
1387 sock_put(newsk); 1291 inet_csk_prepare_forced_close(newsk);
1292 tcp_done(newsk);
1388 goto out; 1293 goto out;
1389 } 1294 }
1390 __inet6_hash(newsk, NULL); 1295 __inet6_hash(newsk, NULL);
@@ -1741,11 +1646,11 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
1741 skb->destructor = sock_edemux; 1646 skb->destructor = sock_edemux;
1742 if (sk->sk_state != TCP_TIME_WAIT) { 1647 if (sk->sk_state != TCP_TIME_WAIT) {
1743 struct dst_entry *dst = sk->sk_rx_dst; 1648 struct dst_entry *dst = sk->sk_rx_dst;
1744 struct inet_sock *icsk = inet_sk(sk); 1649
1745 if (dst) 1650 if (dst)
1746 dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); 1651 dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
1747 if (dst && 1652 if (dst &&
1748 icsk->rx_dst_ifindex == skb->skb_iif) 1653 inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
1749 skb_dst_set_noref(skb, dst); 1654 skb_dst_set_noref(skb, dst);
1750 } 1655 }
1751 } 1656 }
@@ -1866,7 +1771,7 @@ static void get_openreq6(struct seq_file *seq,
1866 0,0, /* could print option size, but that is af dependent. */ 1771 0,0, /* could print option size, but that is af dependent. */
1867 1, /* timers active (only the expire timer) */ 1772 1, /* timers active (only the expire timer) */
1868 jiffies_to_clock_t(ttd), 1773 jiffies_to_clock_t(ttd),
1869 req->retrans, 1774 req->num_timeout,
1870 from_kuid_munged(seq_user_ns(seq), uid), 1775 from_kuid_munged(seq_user_ns(seq), uid),
1871 0, /* non standard timer */ 1776 0, /* non standard timer */
1872 0, /* open_requests have no inode */ 1777 0, /* open_requests have no inode */
@@ -2063,10 +1968,6 @@ static const struct inet6_protocol tcpv6_protocol = {
2063 .early_demux = tcp_v6_early_demux, 1968 .early_demux = tcp_v6_early_demux,
2064 .handler = tcp_v6_rcv, 1969 .handler = tcp_v6_rcv,
2065 .err_handler = tcp_v6_err, 1970 .err_handler = tcp_v6_err,
2066 .gso_send_check = tcp_v6_gso_send_check,
2067 .gso_segment = tcp_tso_segment,
2068 .gro_receive = tcp6_gro_receive,
2069 .gro_complete = tcp6_gro_complete,
2070 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 1971 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
2071}; 1972};
2072 1973
@@ -2121,10 +2022,10 @@ int __init tcpv6_init(void)
2121out: 2022out:
2122 return ret; 2023 return ret;
2123 2024
2124out_tcpv6_protocol:
2125 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
2126out_tcpv6_protosw: 2025out_tcpv6_protosw:
2127 inet6_unregister_protosw(&tcpv6_protosw); 2026 inet6_unregister_protosw(&tcpv6_protosw);
2027out_tcpv6_protocol:
2028 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
2128 goto out; 2029 goto out;
2129} 2030}
2130 2031