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.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 075f540ec197..6603511e3673 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -75,6 +75,9 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
75 struct request_sock *req); 75 struct request_sock *req);
76 76
77static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); 77static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
78static void __tcp_v6_send_check(struct sk_buff *skb,
79 struct in6_addr *saddr,
80 struct in6_addr *daddr);
78 81
79static const struct inet_connection_sock_af_ops ipv6_mapped; 82static const struct inet_connection_sock_af_ops ipv6_mapped;
80static const struct inet_connection_sock_af_ops ipv6_specific; 83static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -350,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
350 if (sk->sk_state == TCP_CLOSE) 353 if (sk->sk_state == TCP_CLOSE)
351 goto out; 354 goto out;
352 355
356 if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
357 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
358 goto out;
359 }
360
353 tp = tcp_sk(sk); 361 tp = tcp_sk(sk);
354 seq = ntohl(th->seq); 362 seq = ntohl(th->seq);
355 if (sk->sk_state != TCP_LISTEN && 363 if (sk->sk_state != TCP_LISTEN &&
@@ -503,14 +511,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
503 511
504 skb = tcp_make_synack(sk, dst, req, rvp); 512 skb = tcp_make_synack(sk, dst, req, rvp);
505 if (skb) { 513 if (skb) {
506 struct tcphdr *th = tcp_hdr(skb); 514 __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
507
508 th->check = tcp_v6_check(skb->len,
509 &treq->loc_addr, &treq->rmt_addr,
510 csum_partial(th, skb->len, skb->csum));
511 515
512 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); 516 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
513 err = ip6_xmit(sk, skb, &fl, opt, 0); 517 err = ip6_xmit(sk, skb, &fl, opt);
514 err = net_xmit_eval(err); 518 err = net_xmit_eval(err);
515 } 519 }
516 520
@@ -918,22 +922,29 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = {
918 .twsk_destructor= tcp_twsk_destructor, 922 .twsk_destructor= tcp_twsk_destructor,
919}; 923};
920 924
921static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) 925static void __tcp_v6_send_check(struct sk_buff *skb,
926 struct in6_addr *saddr, struct in6_addr *daddr)
922{ 927{
923 struct ipv6_pinfo *np = inet6_sk(sk);
924 struct tcphdr *th = tcp_hdr(skb); 928 struct tcphdr *th = tcp_hdr(skb);
925 929
926 if (skb->ip_summed == CHECKSUM_PARTIAL) { 930 if (skb->ip_summed == CHECKSUM_PARTIAL) {
927 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); 931 th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
928 skb->csum_start = skb_transport_header(skb) - skb->head; 932 skb->csum_start = skb_transport_header(skb) - skb->head;
929 skb->csum_offset = offsetof(struct tcphdr, check); 933 skb->csum_offset = offsetof(struct tcphdr, check);
930 } else { 934 } else {
931 th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 935 th->check = tcp_v6_check(skb->len, saddr, daddr,
932 csum_partial(th, th->doff<<2, 936 csum_partial(th, th->doff << 2,
933 skb->csum)); 937 skb->csum));
934 } 938 }
935} 939}
936 940
941static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
942{
943 struct ipv6_pinfo *np = inet6_sk(sk);
944
945 __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
946}
947
937static int tcp_v6_gso_send_check(struct sk_buff *skb) 948static int tcp_v6_gso_send_check(struct sk_buff *skb)
938{ 949{
939 struct ipv6hdr *ipv6h; 950 struct ipv6hdr *ipv6h;
@@ -946,11 +957,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
946 th = tcp_hdr(skb); 957 th = tcp_hdr(skb);
947 958
948 th->check = 0; 959 th->check = 0;
949 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
950 IPPROTO_TCP, 0);
951 skb->csum_start = skb_transport_header(skb) - skb->head;
952 skb->csum_offset = offsetof(struct tcphdr, check);
953 skb->ip_summed = CHECKSUM_PARTIAL; 960 skb->ip_summed = CHECKSUM_PARTIAL;
961 __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
954 return 0; 962 return 0;
955} 963}
956 964
@@ -1047,15 +1055,14 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
1047 } 1055 }
1048#endif 1056#endif
1049 1057
1050 buff->csum = csum_partial(t1, tot_len, 0);
1051
1052 memset(&fl, 0, sizeof(fl)); 1058 memset(&fl, 0, sizeof(fl));
1053 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); 1059 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
1054 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); 1060 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
1055 1061
1056 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, 1062 buff->ip_summed = CHECKSUM_PARTIAL;
1057 tot_len, IPPROTO_TCP, 1063 buff->csum = 0;
1058 buff->csum); 1064
1065 __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst);
1059 1066
1060 fl.proto = IPPROTO_TCP; 1067 fl.proto = IPPROTO_TCP;
1061 fl.oif = inet6_iif(skb); 1068 fl.oif = inet6_iif(skb);
@@ -1070,7 +1077,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
1070 if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { 1077 if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) {
1071 if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { 1078 if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) {
1072 skb_dst_set(buff, dst); 1079 skb_dst_set(buff, dst);
1073 ip6_xmit(ctl_sk, buff, &fl, NULL, 0); 1080 ip6_xmit(ctl_sk, buff, &fl, NULL);
1074 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); 1081 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
1075 if (rst) 1082 if (rst)
1076 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); 1083 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
@@ -1233,12 +1240,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1233 goto drop_and_free; 1240 goto drop_and_free;
1234 1241
1235 /* Secret recipe starts with IP addresses */ 1242 /* Secret recipe starts with IP addresses */
1236 d = &ipv6_hdr(skb)->daddr.s6_addr32[0]; 1243 d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0];
1237 *mess++ ^= *d++; 1244 *mess++ ^= *d++;
1238 *mess++ ^= *d++; 1245 *mess++ ^= *d++;
1239 *mess++ ^= *d++; 1246 *mess++ ^= *d++;
1240 *mess++ ^= *d++; 1247 *mess++ ^= *d++;
1241 d = &ipv6_hdr(skb)->saddr.s6_addr32[0]; 1248 d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0];
1242 *mess++ ^= *d++; 1249 *mess++ ^= *d++;
1243 *mess++ ^= *d++; 1250 *mess++ ^= *d++;
1244 *mess++ ^= *d++; 1251 *mess++ ^= *d++;
@@ -1676,6 +1683,7 @@ ipv6_pktoptions:
1676static int tcp_v6_rcv(struct sk_buff *skb) 1683static int tcp_v6_rcv(struct sk_buff *skb)
1677{ 1684{
1678 struct tcphdr *th; 1685 struct tcphdr *th;
1686 struct ipv6hdr *hdr;
1679 struct sock *sk; 1687 struct sock *sk;
1680 int ret; 1688 int ret;
1681 struct net *net = dev_net(skb->dev); 1689 struct net *net = dev_net(skb->dev);
@@ -1702,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb)
1702 goto bad_packet; 1710 goto bad_packet;
1703 1711
1704 th = tcp_hdr(skb); 1712 th = tcp_hdr(skb);
1713 hdr = ipv6_hdr(skb);
1705 TCP_SKB_CB(skb)->seq = ntohl(th->seq); 1714 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1706 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + 1715 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1707 skb->len - th->doff*4); 1716 skb->len - th->doff*4);
1708 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); 1717 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1709 TCP_SKB_CB(skb)->when = 0; 1718 TCP_SKB_CB(skb)->when = 0;
1710 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); 1719 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr);
1711 TCP_SKB_CB(skb)->sacked = 0; 1720 TCP_SKB_CB(skb)->sacked = 0;
1712 1721
1713 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); 1722 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
@@ -1718,6 +1727,11 @@ process:
1718 if (sk->sk_state == TCP_TIME_WAIT) 1727 if (sk->sk_state == TCP_TIME_WAIT)
1719 goto do_time_wait; 1728 goto do_time_wait;
1720 1729
1730 if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
1731 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
1732 goto discard_and_relse;
1733 }
1734
1721 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 1735 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1722 goto discard_and_relse; 1736 goto discard_and_relse;
1723 1737