diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index bd5ef7b6e48e..6603511e3673 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -353,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
353 | if (sk->sk_state == TCP_CLOSE) | 353 | if (sk->sk_state == TCP_CLOSE) |
354 | goto out; | 354 | goto out; |
355 | 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 | |||
356 | tp = tcp_sk(sk); | 361 | tp = tcp_sk(sk); |
357 | seq = ntohl(th->seq); | 362 | seq = ntohl(th->seq); |
358 | if (sk->sk_state != TCP_LISTEN && | 363 | if (sk->sk_state != TCP_LISTEN && |
@@ -1018,7 +1023,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1018 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); | 1023 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); |
1019 | 1024 | ||
1020 | t1 = (struct tcphdr *) skb_push(buff, tot_len); | 1025 | t1 = (struct tcphdr *) skb_push(buff, tot_len); |
1021 | skb_reset_transport_header(skb); | 1026 | skb_reset_transport_header(buff); |
1022 | 1027 | ||
1023 | /* Swap the send and the receive. */ | 1028 | /* Swap the send and the receive. */ |
1024 | memset(t1, 0, sizeof(*t1)); | 1029 | memset(t1, 0, sizeof(*t1)); |
@@ -1050,12 +1055,13 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1050 | } | 1055 | } |
1051 | #endif | 1056 | #endif |
1052 | 1057 | ||
1053 | buff->csum = csum_partial(t1, tot_len, 0); | ||
1054 | |||
1055 | memset(&fl, 0, sizeof(fl)); | 1058 | memset(&fl, 0, sizeof(fl)); |
1056 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 1059 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
1057 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | 1060 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); |
1058 | 1061 | ||
1062 | buff->ip_summed = CHECKSUM_PARTIAL; | ||
1063 | buff->csum = 0; | ||
1064 | |||
1059 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); | 1065 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); |
1060 | 1066 | ||
1061 | fl.proto = IPPROTO_TCP; | 1067 | fl.proto = IPPROTO_TCP; |
@@ -1234,12 +1240,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1234 | goto drop_and_free; | 1240 | goto drop_and_free; |
1235 | 1241 | ||
1236 | /* Secret recipe starts with IP addresses */ | 1242 | /* Secret recipe starts with IP addresses */ |
1237 | d = &ipv6_hdr(skb)->daddr.s6_addr32[0]; | 1243 | d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0]; |
1238 | *mess++ ^= *d++; | 1244 | *mess++ ^= *d++; |
1239 | *mess++ ^= *d++; | 1245 | *mess++ ^= *d++; |
1240 | *mess++ ^= *d++; | 1246 | *mess++ ^= *d++; |
1241 | *mess++ ^= *d++; | 1247 | *mess++ ^= *d++; |
1242 | d = &ipv6_hdr(skb)->saddr.s6_addr32[0]; | 1248 | d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0]; |
1243 | *mess++ ^= *d++; | 1249 | *mess++ ^= *d++; |
1244 | *mess++ ^= *d++; | 1250 | *mess++ ^= *d++; |
1245 | *mess++ ^= *d++; | 1251 | *mess++ ^= *d++; |
@@ -1677,6 +1683,7 @@ ipv6_pktoptions: | |||
1677 | static int tcp_v6_rcv(struct sk_buff *skb) | 1683 | static int tcp_v6_rcv(struct sk_buff *skb) |
1678 | { | 1684 | { |
1679 | struct tcphdr *th; | 1685 | struct tcphdr *th; |
1686 | struct ipv6hdr *hdr; | ||
1680 | struct sock *sk; | 1687 | struct sock *sk; |
1681 | int ret; | 1688 | int ret; |
1682 | struct net *net = dev_net(skb->dev); | 1689 | struct net *net = dev_net(skb->dev); |
@@ -1703,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1703 | goto bad_packet; | 1710 | goto bad_packet; |
1704 | 1711 | ||
1705 | th = tcp_hdr(skb); | 1712 | th = tcp_hdr(skb); |
1713 | hdr = ipv6_hdr(skb); | ||
1706 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | 1714 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); |
1707 | 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 + |
1708 | skb->len - th->doff*4); | 1716 | skb->len - th->doff*4); |
1709 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1717 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
1710 | TCP_SKB_CB(skb)->when = 0; | 1718 | TCP_SKB_CB(skb)->when = 0; |
1711 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1719 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr); |
1712 | TCP_SKB_CB(skb)->sacked = 0; | 1720 | TCP_SKB_CB(skb)->sacked = 0; |
1713 | 1721 | ||
1714 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); | 1722 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
@@ -1719,6 +1727,11 @@ process: | |||
1719 | if (sk->sk_state == TCP_TIME_WAIT) | 1727 | if (sk->sk_state == TCP_TIME_WAIT) |
1720 | goto do_time_wait; | 1728 | goto do_time_wait; |
1721 | 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 | |||
1722 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1735 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
1723 | goto discard_and_relse; | 1736 | goto discard_and_relse; |
1724 | 1737 | ||