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 | ||
